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 = window.ConversationController || {};
|
||||||
window.ConversationController.isSignalConversation = () => false;
|
window.ConversationController.isSignalConversationId = () => false;
|
||||||
window.ConversationController.onConvoMessageMount = noop;
|
window.ConversationController.onConvoMessageMount = noop;
|
||||||
window.getPreferredSystemLocales = () => ['en'];
|
window.getPreferredSystemLocales = () => ['en'];
|
||||||
window.getResolvedMessagesLocaleDirection = () => 'ltr';
|
window.getResolvedMessagesLocaleDirection = () => 'ltr';
|
||||||
|
|
|
@ -92,8 +92,9 @@
|
||||||
"@react-aria/utils": "3.16.0",
|
"@react-aria/utils": "3.16.0",
|
||||||
"@react-spring/web": "9.5.5",
|
"@react-spring/web": "9.5.5",
|
||||||
"@signalapp/better-sqlite3": "8.4.3",
|
"@signalapp/better-sqlite3": "8.4.3",
|
||||||
"@signalapp/libsignal-client": "0.29.1",
|
"@signalapp/libsignal-client": "0.30.2",
|
||||||
"@signalapp/ringrtc": "2.30.0",
|
"@signalapp/ringrtc": "2.30.0",
|
||||||
|
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
||||||
"@types/fabric": "4.5.3",
|
"@types/fabric": "4.5.3",
|
||||||
"backbone": "1.4.0",
|
"backbone": "1.4.0",
|
||||||
"blob-util": "2.0.2",
|
"blob-util": "2.0.2",
|
||||||
|
@ -180,7 +181,6 @@
|
||||||
"uuid": "3.3.2",
|
"uuid": "3.3.2",
|
||||||
"uuid-browser": "3.1.0",
|
"uuid-browser": "3.1.0",
|
||||||
"websocket": "1.0.34",
|
"websocket": "1.0.34",
|
||||||
"@signalapp/windows-dummy-keystroke": "1.0.0",
|
|
||||||
"zod": "3.21.4"
|
"zod": "3.21.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
"@electron/fuses": "1.5.0",
|
"@electron/fuses": "1.5.0",
|
||||||
"@formatjs/intl": "2.6.7",
|
"@formatjs/intl": "2.6.7",
|
||||||
"@mixer/parallel-prettier": "2.0.3",
|
"@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-a11y": "6.5.6",
|
||||||
"@storybook/addon-actions": "6.5.6",
|
"@storybook/addon-actions": "6.5.6",
|
||||||
"@storybook/addon-controls": "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
|
uint32 version = 2; // The change version number
|
||||||
repeated AddMemberAction addMembers = 3; // Members added
|
repeated AddMemberAction addMembers = 3; // Members added
|
||||||
repeated DeleteMemberAction deleteMembers = 4; // Members deleted
|
repeated DeleteMemberAction deleteMembers = 4; // Members deleted
|
||||||
|
|
|
@ -136,7 +136,7 @@ message AccountRecord {
|
||||||
|
|
||||||
message PinnedConversation {
|
message PinnedConversation {
|
||||||
message Contact {
|
message Contact {
|
||||||
optional string uuid = 1;
|
optional string serviceId = 1;
|
||||||
optional string e164 = 2;
|
optional string e164 = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,9 @@ export async function populateConversationWithMessages({
|
||||||
schemaVersion: window.Signal.Types.Message.CURRENT_SCHEMA_VERSION,
|
schemaVersion: window.Signal.Types.Message.CURRENT_SCHEMA_VERSION,
|
||||||
received_at: incrementMessageCounter(),
|
received_at: incrementMessageCounter(),
|
||||||
readStatus: isUnread ? ReadStatus.Unread : ReadStatus.Read,
|
readStatus: isUnread ? ReadStatus.Unread : ReadStatus.Read,
|
||||||
sourceUuid: isIncoming ? conversation.getCheckedServiceId('CI') : ourAci,
|
sourceServiceId: isIncoming
|
||||||
|
? conversation.getCheckedServiceId('CI')
|
||||||
|
: ourAci,
|
||||||
...(isIncoming
|
...(isIncoming
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
|
|
|
@ -22,11 +22,12 @@ import { maybeDeriveGroupV2Id } from './groups';
|
||||||
import { assertDev, strictAssert } from './util/assert';
|
import { assertDev, strictAssert } from './util/assert';
|
||||||
import { drop } from './util/drop';
|
import { drop } from './util/drop';
|
||||||
import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation';
|
import { isGroupV1, isGroupV2 } from './util/whatTypeOfConversation';
|
||||||
import type { ServiceIdString } from './types/ServiceId';
|
import type { ServiceIdString, AciString, PniString } from './types/ServiceId';
|
||||||
import {
|
import {
|
||||||
isServiceIdString,
|
isServiceIdString,
|
||||||
normalizeAci,
|
normalizeAci,
|
||||||
normalizePni,
|
normalizePni,
|
||||||
|
normalizeServiceId,
|
||||||
} from './types/ServiceId';
|
} from './types/ServiceId';
|
||||||
import { sleep } from './util/sleep';
|
import { sleep } from './util/sleep';
|
||||||
import { isNotNil } from './util/isNotNil';
|
import { isNotNil } from './util/isNotNil';
|
||||||
|
@ -40,7 +41,7 @@ import { countAllConversationsUnreadStats } from './util/countUnreadStats';
|
||||||
|
|
||||||
type ConvoMatchType =
|
type ConvoMatchType =
|
||||||
| {
|
| {
|
||||||
key: 'uuid' | 'pni';
|
key: 'serviceId' | 'pni';
|
||||||
value: ServiceIdString | undefined;
|
value: ServiceIdString | undefined;
|
||||||
match: ConversationModel | undefined;
|
match: ConversationModel | undefined;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +56,7 @@ const { hasOwnProperty } = Object.prototype;
|
||||||
function applyChangeToConversation(
|
function applyChangeToConversation(
|
||||||
conversation: ConversationModel,
|
conversation: ConversationModel,
|
||||||
suggestedChange: Partial<
|
suggestedChange: Partial<
|
||||||
Pick<ConversationAttributesType, 'uuid' | 'e164' | 'pni'>
|
Pick<ConversationAttributesType, 'serviceId' | 'e164' | 'pni'>
|
||||||
>
|
>
|
||||||
) {
|
) {
|
||||||
const change = { ...suggestedChange };
|
const change = { ...suggestedChange };
|
||||||
|
@ -65,29 +66,29 @@ function applyChangeToConversation(
|
||||||
change.pni = undefined;
|
change.pni = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a PNI but not an ACI, then the PNI will go in the UUID field
|
// 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 uuid slot
|
// Tricky: We need a special check here, because the PNI can be in the serviceId slot
|
||||||
if (
|
if (
|
||||||
change.pni &&
|
change.pni &&
|
||||||
!change.uuid &&
|
!change.serviceId &&
|
||||||
(!conversation.get('uuid') ||
|
(!conversation.getServiceId() ||
|
||||||
conversation.get('uuid') === conversation.get('pni'))
|
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 (
|
if (
|
||||||
!change.uuid &&
|
!change.serviceId &&
|
||||||
hasOwnProperty.call(change, 'pni') &&
|
hasOwnProperty.call(change, 'pni') &&
|
||||||
!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')) {
|
if (hasOwnProperty.call(change, 'serviceId')) {
|
||||||
conversation.updateUuid(change.uuid);
|
conversation.updateServiceId(change.serviceId);
|
||||||
}
|
}
|
||||||
if (hasOwnProperty.call(change, 'e164')) {
|
if (hasOwnProperty.call(change, 'e164')) {
|
||||||
conversation.updateE164(change.e164);
|
conversation.updateE164(change.e164);
|
||||||
|
@ -289,7 +290,7 @@ export class ConversationController {
|
||||||
if (type === 'group') {
|
if (type === 'group') {
|
||||||
conversation = this._conversations.add({
|
conversation = this._conversations.add({
|
||||||
id,
|
id,
|
||||||
uuid: undefined,
|
serviceId: undefined,
|
||||||
e164: undefined,
|
e164: undefined,
|
||||||
groupId: identifier,
|
groupId: identifier,
|
||||||
type,
|
type,
|
||||||
|
@ -299,7 +300,7 @@ export class ConversationController {
|
||||||
} else if (isServiceIdString(identifier)) {
|
} else if (isServiceIdString(identifier)) {
|
||||||
conversation = this._conversations.add({
|
conversation = this._conversations.add({
|
||||||
id,
|
id,
|
||||||
uuid: identifier,
|
serviceId: identifier,
|
||||||
e164: undefined,
|
e164: undefined,
|
||||||
groupId: undefined,
|
groupId: undefined,
|
||||||
type,
|
type,
|
||||||
|
@ -309,7 +310,7 @@ export class ConversationController {
|
||||||
} else {
|
} else {
|
||||||
conversation = this._conversations.add({
|
conversation = this._conversations.add({
|
||||||
id,
|
id,
|
||||||
uuid: undefined,
|
serviceId: undefined,
|
||||||
e164: identifier,
|
e164: identifier,
|
||||||
groupId: undefined,
|
groupId: undefined,
|
||||||
type,
|
type,
|
||||||
|
@ -455,12 +456,8 @@ export class ConversationController {
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
|
|
||||||
isSignalConversation(uuidOrId: string): boolean {
|
isSignalConversationId(conversationId: string): boolean {
|
||||||
if (uuidOrId === SIGNAL_ACI) {
|
return this._signalConversationId === conversationId;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._signalConversationId === uuidOrId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
areWePrimaryDevice(): boolean {
|
areWePrimaryDevice(): boolean {
|
||||||
|
@ -469,7 +466,7 @@ export class ConversationController {
|
||||||
return ourDeviceId === 1;
|
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({
|
maybeMergeContacts({
|
||||||
aci: providedAci,
|
aci: providedAci,
|
||||||
e164,
|
e164,
|
||||||
|
@ -478,9 +475,9 @@ export class ConversationController {
|
||||||
fromPniSignature,
|
fromPniSignature,
|
||||||
mergeOldAndNew = safeCombineConversations,
|
mergeOldAndNew = safeCombineConversations,
|
||||||
}: {
|
}: {
|
||||||
aci?: string;
|
aci?: AciString;
|
||||||
e164?: string;
|
e164?: string;
|
||||||
pni?: string;
|
pni?: PniString;
|
||||||
reason: string;
|
reason: string;
|
||||||
fromPniSignature?: boolean;
|
fromPniSignature?: boolean;
|
||||||
mergeOldAndNew?: (options: SafeCombineConversationsParams) => Promise<void>;
|
mergeOldAndNew?: (options: SafeCombineConversationsParams) => Promise<void>;
|
||||||
|
@ -500,8 +497,7 @@ export class ConversationController {
|
||||||
}
|
}
|
||||||
const logId = `maybeMergeContacts/${reason}/${dataProvided.join(',')}`;
|
const logId = `maybeMergeContacts/${reason}/${dataProvided.join(',')}`;
|
||||||
|
|
||||||
const aci =
|
const aci = providedAci
|
||||||
providedAci && providedAci !== providedPni
|
|
||||||
? normalizeAci(providedAci, 'maybeMergeContacts.aci')
|
? normalizeAci(providedAci, 'maybeMergeContacts.aci')
|
||||||
: undefined;
|
: undefined;
|
||||||
const pni = providedPni
|
const pni = providedPni
|
||||||
|
@ -517,7 +513,7 @@ export class ConversationController {
|
||||||
|
|
||||||
const matches: Array<ConvoMatchType> = [
|
const matches: Array<ConvoMatchType> = [
|
||||||
{
|
{
|
||||||
key: 'uuid',
|
key: 'serviceId',
|
||||||
value: aci,
|
value: aci,
|
||||||
match: window.ConversationController.get(aci),
|
match: window.ConversationController.get(aci),
|
||||||
},
|
},
|
||||||
|
@ -568,26 +564,26 @@ export class ConversationController {
|
||||||
);
|
);
|
||||||
targetConversation = match;
|
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 (
|
if (
|
||||||
!targetConversation &&
|
!targetConversation &&
|
||||||
unused.key === 'uuid' &&
|
unused.key === 'serviceId' &&
|
||||||
match.get(unused.key) === pni
|
match.get(unused.key) === pni
|
||||||
) {
|
) {
|
||||||
log.info(
|
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()}`
|
`so it will be our target conversation - ${match.idForLogging()}`
|
||||||
);
|
);
|
||||||
targetConversation = match;
|
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 (
|
if (
|
||||||
!targetConversation &&
|
!targetConversation &&
|
||||||
unused.key === 'uuid' &&
|
unused.key === 'serviceId' &&
|
||||||
match.get(unused.key) === match.get('pni')
|
match.get(unused.key) === match.getPni()
|
||||||
) {
|
) {
|
||||||
log.info(
|
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()}`
|
`so it will be our target conversation - ${match.idForLogging()}`
|
||||||
);
|
);
|
||||||
targetConversation = match;
|
targetConversation = match;
|
||||||
|
@ -640,20 +636,21 @@ export class ConversationController {
|
||||||
);
|
);
|
||||||
const change: Pick<
|
const change: Pick<
|
||||||
Partial<ConversationAttributesType>,
|
Partial<ConversationAttributesType>,
|
||||||
'uuid' | 'e164' | 'pni'
|
'serviceId' | 'e164' | 'pni'
|
||||||
> = {
|
> = {
|
||||||
[key]: undefined,
|
[key]: undefined,
|
||||||
};
|
};
|
||||||
// When the PNI is being used in the uuid field alone, we need to clear it
|
// When the PNI is being used in the serviceId field alone, we need to clear it
|
||||||
if ((key === 'pni' || key === 'e164') && match.get('uuid') === pni) {
|
if ((key === 'pni' || key === 'e164') && match.getServiceId() === pni) {
|
||||||
change.uuid = undefined;
|
change.serviceId = undefined;
|
||||||
}
|
}
|
||||||
applyChangeToConversation(match, change);
|
applyChangeToConversation(match, change);
|
||||||
|
|
||||||
// Note: The PNI check here is just to be bulletproof; if we know a UUID is a PNI,
|
// Note: The PNI check here is just to be bulletproof; if we know a
|
||||||
// then that should be put in the UUID field as well!
|
// serviceId is a PNI, then that should be put in the serviceId field
|
||||||
|
// as well!
|
||||||
const willMerge =
|
const willMerge =
|
||||||
!match.get('uuid') && !match.get('e164') && !match.get('pni');
|
!match.getServiceId() && !match.get('e164') && !match.getPni();
|
||||||
|
|
||||||
applyChangeToConversation(targetConversation, {
|
applyChangeToConversation(targetConversation, {
|
||||||
[key]: value,
|
[key]: value,
|
||||||
|
@ -705,7 +702,7 @@ export class ConversationController {
|
||||||
log.info(`${logId}: Creating a new conversation with all inputs`);
|
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
|
// 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;
|
const identifier = aci || pni || e164;
|
||||||
strictAssert(identifier, `${logId}: identifier must be truthy!`);
|
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;
|
* database id of the given contact. Will create a new conversation if none exists;
|
||||||
* otherwise will return whatever is found.
|
* otherwise will return whatever is found.
|
||||||
*/
|
*/
|
||||||
lookupOrCreate({
|
lookupOrCreate({
|
||||||
e164,
|
e164,
|
||||||
uuid,
|
serviceId,
|
||||||
reason,
|
reason,
|
||||||
}: {
|
}: {
|
||||||
e164?: string | null;
|
e164?: string | null;
|
||||||
uuid?: string | null;
|
serviceId?: ServiceIdString | null;
|
||||||
reason: string;
|
reason: string;
|
||||||
}): ConversationModel | undefined {
|
}): ConversationModel | undefined {
|
||||||
const normalizedUuid = uuid ? uuid.toLowerCase() : undefined;
|
const normalizedServiceId = serviceId
|
||||||
const identifier = normalizedUuid || e164;
|
? normalizeServiceId(serviceId, 'ConversationController.lookupOrCreate')
|
||||||
|
: undefined;
|
||||||
|
const identifier = normalizedServiceId || e164;
|
||||||
|
|
||||||
if ((!e164 && !uuid) || !identifier) {
|
if ((!e164 && !serviceId) || !identifier) {
|
||||||
log.warn(
|
log.warn(
|
||||||
`lookupOrCreate: Called with neither e164 nor uuid! reason: ${reason}`
|
`lookupOrCreate: Called with neither e164 nor serviceId! reason: ${reason}`
|
||||||
);
|
);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const convoE164 = this.get(e164);
|
const convoE164 = this.get(e164);
|
||||||
const convoUuid = this.get(normalizedUuid);
|
const convoServiceId = this.get(normalizedServiceId);
|
||||||
|
|
||||||
// 1. Handle no match at all
|
// 1. Handle no match at all
|
||||||
if (!convoE164 && !convoUuid) {
|
if (!convoE164 && !convoServiceId) {
|
||||||
log.info('lookupOrCreate: Creating new contact, no matches found');
|
log.info('lookupOrCreate: Creating new contact, no matches found');
|
||||||
const newConvo = this.getOrCreate(identifier, 'private');
|
const newConvo = this.getOrCreate(identifier, 'private');
|
||||||
|
|
||||||
// `identifier` would resolve to uuid if we had both, so fix up e164
|
// `identifier` would resolve to serviceId if we had both, so fix up e164
|
||||||
if (normalizedUuid && e164) {
|
if (normalizedServiceId && e164) {
|
||||||
newConvo.updateE164(e164);
|
newConvo.updateE164(e164);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newConvo;
|
return newConvo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Handle match on only UUID
|
// 2. Handle match on only service id
|
||||||
if (!convoE164 && convoUuid) {
|
if (!convoE164 && convoServiceId) {
|
||||||
return convoUuid;
|
return convoServiceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Handle match on only E164
|
// 3. Handle match on only E164
|
||||||
if (convoE164 && !convoUuid) {
|
if (convoE164 && !convoServiceId) {
|
||||||
return convoE164;
|
return convoE164;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For some reason, TypeScript doesn't believe that we can trust that these two values
|
// 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.
|
// are truthy by this point. So we'll throw if that isn't the case.
|
||||||
if (!convoE164 || !convoUuid) {
|
if (!convoE164 || !convoServiceId) {
|
||||||
throw new Error(
|
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
|
// 4. If the two lookups agree, return that conversation
|
||||||
if (convoE164 === convoUuid) {
|
if (convoE164 === convoServiceId) {
|
||||||
return convoUuid;
|
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(
|
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> {
|
checkForConflicts(): Promise<void> {
|
||||||
|
@ -795,7 +794,7 @@ export class ConversationController {
|
||||||
// run on `_combineConversationsQueue` queue and we don't want deadlocks.
|
// run on `_combineConversationsQueue` queue and we don't want deadlocks.
|
||||||
private async doCheckForConflicts(): Promise<void> {
|
private async doCheckForConflicts(): Promise<void> {
|
||||||
log.info('checkForConflicts: starting...');
|
log.info('checkForConflicts: starting...');
|
||||||
const byUuid = Object.create(null);
|
const byServiceId = Object.create(null);
|
||||||
const byE164 = Object.create(null);
|
const byE164 = Object.create(null);
|
||||||
const byGroupV2Id = Object.create(null);
|
const byGroupV2Id = Object.create(null);
|
||||||
// We also want to find duplicate GV1 IDs. You might expect to see a "byGroupV1Id" map
|
// 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'
|
'Expected conversation to be found in array during iteration'
|
||||||
);
|
);
|
||||||
|
|
||||||
const uuid = conversation.get('uuid');
|
const serviceId = conversation.getServiceId();
|
||||||
const pni = conversation.get('pni');
|
const pni = conversation.getPni();
|
||||||
const e164 = conversation.get('e164');
|
const e164 = conversation.get('e164');
|
||||||
|
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
const existing = byUuid[uuid];
|
const existing = byServiceId[serviceId];
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
byUuid[uuid] = conversation;
|
byServiceId[serviceId] = conversation;
|
||||||
} else {
|
} 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
|
// Keep the newer one if it has an e164, otherwise keep existing
|
||||||
if (conversation.get('e164')) {
|
if (conversation.get('e164')) {
|
||||||
|
@ -831,7 +832,7 @@ export class ConversationController {
|
||||||
current: conversation,
|
current: conversation,
|
||||||
obsolete: existing,
|
obsolete: existing,
|
||||||
});
|
});
|
||||||
byUuid[uuid] = conversation;
|
byServiceId[serviceId] = conversation;
|
||||||
} else {
|
} else {
|
||||||
// Keep existing - note that this applies if neither had an e164
|
// Keep existing - note that this applies if neither had an e164
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
@ -844,28 +845,28 @@ export class ConversationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pni) {
|
if (pni) {
|
||||||
const existing = byUuid[pni];
|
const existing = byServiceId[pni];
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
byUuid[pni] = conversation;
|
byServiceId[pni] = conversation;
|
||||||
} else if (existing === 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.
|
// happens when starting a conversation by E164.
|
||||||
assertDev(
|
assertDev(
|
||||||
pni === uuid,
|
pni === serviceId,
|
||||||
'checkForConflicts: expected PNI to be equal to UUID'
|
'checkForConflicts: expected PNI to be equal to serviceId'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
log.warn(`checkForConflicts: Found conflict with pni ${pni}`);
|
log.warn(`checkForConflicts: Found conflict with pni ${pni}`);
|
||||||
|
|
||||||
// Keep the newer one if it has additional data, otherwise keep existing
|
// 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
|
// Keep new one
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await this.doCombineConversations({
|
await this.doCombineConversations({
|
||||||
current: conversation,
|
current: conversation,
|
||||||
obsolete: existing,
|
obsolete: existing,
|
||||||
});
|
});
|
||||||
byUuid[pni] = conversation;
|
byServiceId[pni] = conversation;
|
||||||
} else {
|
} else {
|
||||||
// Keep existing - note that this applies if neither had an e164
|
// Keep existing - note that this applies if neither had an e164
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
@ -882,15 +883,15 @@ export class ConversationController {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
byE164[e164] = conversation;
|
byE164[e164] = conversation;
|
||||||
} else {
|
} else {
|
||||||
// If we have two contacts with the same e164 but different truthy UUIDs, then
|
// If we have two contacts with the same e164 but different truthy
|
||||||
// we'll delete the e164 on the older one
|
// service ids, then we'll delete the e164 on the older one
|
||||||
if (
|
if (
|
||||||
conversation.get('uuid') &&
|
conversation.getServiceId() &&
|
||||||
existing.get('uuid') &&
|
existing.getServiceId() &&
|
||||||
conversation.get('uuid') !== existing.get('uuid')
|
conversation.getServiceId() !== existing.getServiceId()
|
||||||
) {
|
) {
|
||||||
log.warn(
|
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 });
|
existing.set({ e164: undefined });
|
||||||
|
@ -903,8 +904,8 @@ export class ConversationController {
|
||||||
|
|
||||||
log.warn(`checkForConflicts: Found conflict with e164 ${e164}`);
|
log.warn(`checkForConflicts: Found conflict with e164 ${e164}`);
|
||||||
|
|
||||||
// Keep the newer one if it has a UUID, otherwise keep existing
|
// Keep the newer one if it has a service id, otherwise keep existing
|
||||||
if (conversation.get('uuid')) {
|
if (conversation.getServiceId()) {
|
||||||
// Keep new one
|
// Keep new one
|
||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await this.doCombineConversations({
|
await this.doCombineConversations({
|
||||||
|
@ -913,7 +914,7 @@ export class ConversationController {
|
||||||
});
|
});
|
||||||
byE164[e164] = conversation;
|
byE164[e164] = conversation;
|
||||||
} else {
|
} 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
|
// eslint-disable-next-line no-await-in-loop
|
||||||
await this.doCombineConversations({
|
await this.doCombineConversations({
|
||||||
current: existing,
|
current: existing,
|
||||||
|
@ -1073,7 +1074,7 @@ export class ConversationController {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.warn(`${logId}: Delete all sessions tied to old conversationId`);
|
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(
|
await window.textsecure.storage.protocol.removeSessionsByConversation(
|
||||||
obsoleteId
|
obsoleteId
|
||||||
);
|
);
|
||||||
|
@ -1301,9 +1302,9 @@ export class ConversationController {
|
||||||
async _forgetE164(e164: string): Promise<void> {
|
async _forgetE164(e164: string): Promise<void> {
|
||||||
const { server } = window.textsecure;
|
const { server } = window.textsecure;
|
||||||
strictAssert(server, 'Server must be initialized');
|
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}`);
|
log.info(`ConversationController: forgetting e164=${e164} pni=${pni}`);
|
||||||
|
|
||||||
|
@ -1382,14 +1383,16 @@ export class ConversationController {
|
||||||
updateConversation(conversation.attributes);
|
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 e164 = conversation.get('e164');
|
||||||
const uuid = conversation.get('uuid');
|
const serviceId = conversation.getServiceId();
|
||||||
if (e164 && isServiceIdString(e164) && uuid) {
|
if (e164 && isServiceIdString(e164) && serviceId) {
|
||||||
conversation.set({ e164: undefined });
|
conversation.set({ e164: undefined });
|
||||||
updateConversation(conversation.attributes);
|
updateConversation(conversation.attributes);
|
||||||
|
|
||||||
log.info(`Cleaning up conversation(${uuid}) with invalid e164`);
|
log.info(
|
||||||
|
`Cleaning up conversation(${serviceId}) with invalid e164`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
|
|
|
@ -423,7 +423,8 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
.map(item => item.fromDB)
|
.map(item => item.fromDB)
|
||||||
.filter(
|
.filter(
|
||||||
item =>
|
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,
|
isConfirmed: key.isConfirmed,
|
||||||
isLastResort: key.isLastResort,
|
isLastResort: key.isLastResort,
|
||||||
keyId: key.keyId,
|
keyId: key.keyId,
|
||||||
ourUuid: ourServiceId,
|
ourServiceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
toSave.push(kyberPreKey);
|
toSave.push(kyberPreKey);
|
||||||
|
@ -589,7 +590,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const entries = Array.from(this.preKeys.values());
|
const entries = Array.from(this.preKeys.values());
|
||||||
return entries
|
return entries
|
||||||
.map(item => item.fromDB)
|
.map(item => item.fromDB)
|
||||||
.filter(item => item.ourUuid === ourServiceId);
|
.filter(item => item.ourServiceId === ourServiceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async storePreKeys(
|
async storePreKeys(
|
||||||
|
@ -613,7 +614,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const preKey = {
|
const preKey = {
|
||||||
id,
|
id,
|
||||||
keyId: key.keyId,
|
keyId: key.keyId,
|
||||||
ourUuid: ourServiceId,
|
ourServiceId,
|
||||||
publicKey: key.keyPair.pubKey,
|
publicKey: key.keyPair.pubKey,
|
||||||
privateKey: key.keyPair.privKey,
|
privateKey: key.keyPair.privKey,
|
||||||
createdAt: now,
|
createdAt: now,
|
||||||
|
@ -705,7 +706,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
const entries = Array.from(this.signedPreKeys.values());
|
const entries = Array.from(this.signedPreKeys.values());
|
||||||
return entries
|
return entries
|
||||||
.filter(({ fromDB }) => fromDB.ourUuid === ourServiceId)
|
.filter(({ fromDB }) => fromDB.ourServiceId === ourServiceId)
|
||||||
.map(entry => {
|
.map(entry => {
|
||||||
const preKey = entry.fromDB;
|
const preKey = entry.fromDB;
|
||||||
return {
|
return {
|
||||||
|
@ -760,7 +761,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
const fromDB = {
|
const fromDB = {
|
||||||
id,
|
id,
|
||||||
ourUuid: ourServiceId,
|
ourServiceId,
|
||||||
keyId,
|
keyId,
|
||||||
publicKey: keyPair.pubKey,
|
publicKey: keyPair.pubKey,
|
||||||
privateKey: keyPair.privKey,
|
privateKey: keyPair.privKey,
|
||||||
|
@ -1335,7 +1336,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
throw new Error('_maybeMigrateSession: Unknown session version type!');
|
throw new Error('_maybeMigrateSession: Unknown session version type!');
|
||||||
}
|
}
|
||||||
|
|
||||||
const ourServiceId = session.ourUuid;
|
const { ourServiceId } = session;
|
||||||
|
|
||||||
const keyPair = this.getIdentityKeyPair(ourServiceId);
|
const keyPair = this.getIdentityKeyPair(ourServiceId);
|
||||||
if (!keyPair) {
|
if (!keyPair) {
|
||||||
|
@ -1384,7 +1385,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const { serviceId, deviceId } = qualifiedAddress;
|
const { serviceId, deviceId } = qualifiedAddress;
|
||||||
|
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.lookupOrCreate({
|
||||||
uuid: serviceId,
|
serviceId,
|
||||||
reason: 'SignalProtocolStore.storeSession',
|
reason: 'SignalProtocolStore.storeSession',
|
||||||
});
|
});
|
||||||
strictAssert(
|
strictAssert(
|
||||||
|
@ -1397,9 +1398,9 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const fromDB = {
|
const fromDB = {
|
||||||
id,
|
id,
|
||||||
version: 2,
|
version: 2,
|
||||||
ourUuid: qualifiedAddress.ourServiceId,
|
ourServiceId: qualifiedAddress.ourServiceId,
|
||||||
conversationId: conversation.id,
|
conversationId: conversation.id,
|
||||||
uuid: serviceId,
|
serviceId,
|
||||||
deviceId,
|
deviceId,
|
||||||
record: record.serialize().toString('base64'),
|
record: record.serialize().toString('base64'),
|
||||||
};
|
};
|
||||||
|
@ -1448,7 +1449,8 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const allSessions = this._getAllSessions();
|
const allSessions = this._getAllSessions();
|
||||||
const entries = allSessions.filter(
|
const entries = allSessions.filter(
|
||||||
({ fromDB }) =>
|
({ fromDB }) =>
|
||||||
fromDB.ourUuid === ourServiceId && serviceIdSet.has(fromDB.uuid)
|
fromDB.ourServiceId === ourServiceId &&
|
||||||
|
serviceIdSet.has(fromDB.serviceId)
|
||||||
);
|
);
|
||||||
const openEntries: Array<
|
const openEntries: Array<
|
||||||
| undefined
|
| undefined
|
||||||
|
@ -1485,15 +1487,15 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
}
|
}
|
||||||
const { entry, record } = item;
|
const { entry, record } = item;
|
||||||
|
|
||||||
const { uuid } = entry.fromDB;
|
const { serviceId } = entry.fromDB;
|
||||||
serviceIdSet.delete(uuid);
|
serviceIdSet.delete(serviceId);
|
||||||
|
|
||||||
const id = entry.fromDB.deviceId;
|
const id = entry.fromDB.deviceId;
|
||||||
|
|
||||||
const registrationId = record.remoteRegistrationId();
|
const registrationId = record.remoteRegistrationId();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
serviceId: uuid,
|
serviceId,
|
||||||
id,
|
id,
|
||||||
registrationId,
|
registrationId,
|
||||||
};
|
};
|
||||||
|
@ -1601,7 +1603,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
for (let i = 0, max = entries.length; i < max; i += 1) {
|
for (let i = 0, max = entries.length; i < max; i += 1) {
|
||||||
const entry = entries[i];
|
const entry = entries[i];
|
||||||
if (entry.fromDB.uuid === serviceId) {
|
if (entry.fromDB.serviceId === serviceId) {
|
||||||
this.sessions.delete(entry.fromDB.id);
|
this.sessions.delete(entry.fromDB.id);
|
||||||
this.pendingSessions.delete(entry.fromDB.id);
|
this.pendingSessions.delete(entry.fromDB.id);
|
||||||
}
|
}
|
||||||
|
@ -1675,7 +1677,8 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
const allEntries = this._getAllSessions();
|
const allEntries = this._getAllSessions();
|
||||||
const entries = allEntries.filter(
|
const entries = allEntries.filter(
|
||||||
entry =>
|
entry =>
|
||||||
entry.fromDB.uuid === serviceId && entry.fromDB.deviceId !== deviceId
|
entry.fromDB.serviceId === serviceId &&
|
||||||
|
entry.fromDB.deviceId !== deviceId
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
@ -1696,7 +1699,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
const allEntries = this._getAllSessions();
|
const allEntries = this._getAllSessions();
|
||||||
const entries = allEntries.filter(
|
const entries = allEntries.filter(
|
||||||
entry => entry.fromDB.uuid === serviceId
|
entry => entry.fromDB.serviceId === serviceId
|
||||||
);
|
);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
@ -1743,7 +1746,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
|
|
||||||
// First, fetch this conversation
|
// First, fetch this conversation
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.lookupOrCreate({
|
||||||
uuid: serviceId,
|
serviceId,
|
||||||
reason: 'SignalProtocolStore.lightSessionReset',
|
reason: 'SignalProtocolStore.lightSessionReset',
|
||||||
});
|
});
|
||||||
assertDev(conversation, `lightSessionReset/${id}: missing conversation`);
|
assertDev(conversation, `lightSessionReset/${id}: missing conversation`);
|
||||||
|
@ -2584,7 +2587,7 @@ export class SignalProtocolStore extends EventEmitter {
|
||||||
isConfirmed: true,
|
isConfirmed: true,
|
||||||
isLastResort: true,
|
isLastResort: true,
|
||||||
keyId: lastResortKyberPreKey.id(),
|
keyId: lastResortKyberPreKey.id(),
|
||||||
ourUuid: pni,
|
ourServiceId: pni,
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ export async function startApp(): Promise<void> {
|
||||||
`retryPlaceholders/interval: Found ${expired.length} expired items`
|
`retryPlaceholders/interval: Found ${expired.length} expired items`
|
||||||
);
|
);
|
||||||
expired.forEach(item => {
|
expired.forEach(item => {
|
||||||
const { conversationId, senderUuid, sentAt } = item;
|
const { conversationId, senderAci, sentAt } = item;
|
||||||
const conversation =
|
const conversation =
|
||||||
window.ConversationController.get(conversationId);
|
window.ConversationController.get(conversationId);
|
||||||
if (conversation) {
|
if (conversation) {
|
||||||
|
@ -1092,7 +1092,7 @@ export async function startApp(): Promise<void> {
|
||||||
conversation.addDeliveryIssue({
|
conversation.addDeliveryIssue({
|
||||||
receivedAt,
|
receivedAt,
|
||||||
receivedAtCounter,
|
receivedAtCounter,
|
||||||
senderUuid,
|
senderAci,
|
||||||
sentAt,
|
sentAt,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -2469,7 +2469,7 @@ export async function startApp(): Promise<void> {
|
||||||
remove: reaction.remove,
|
remove: reaction.remove,
|
||||||
source: ReactionSource.FromSomeoneElse,
|
source: ReactionSource.FromSomeoneElse,
|
||||||
storyReactionMessage: message,
|
storyReactionMessage: message,
|
||||||
targetAuthorUuid: targetAuthorAci,
|
targetAuthorAci,
|
||||||
targetTimestamp: reaction.targetTimestamp,
|
targetTimestamp: reaction.targetTimestamp,
|
||||||
timestamp,
|
timestamp,
|
||||||
};
|
};
|
||||||
|
@ -2679,7 +2679,7 @@ export async function startApp(): Promise<void> {
|
||||||
serverTimestamp: data.serverTimestamp,
|
serverTimestamp: data.serverTimestamp,
|
||||||
source: window.textsecure.storage.user.getNumber(),
|
source: window.textsecure.storage.user.getNumber(),
|
||||||
sourceDevice: data.device,
|
sourceDevice: data.device,
|
||||||
sourceUuid: window.textsecure.storage.user.getAci(),
|
sourceServiceId: window.textsecure.storage.user.getAci(),
|
||||||
timestamp,
|
timestamp,
|
||||||
type: data.message.isStory ? 'story' : 'outgoing',
|
type: data.message.isStory ? 'story' : 'outgoing',
|
||||||
storyDistributionListId: data.storyDistributionListId,
|
storyDistributionListId: data.storyDistributionListId,
|
||||||
|
@ -2755,8 +2755,8 @@ export async function startApp(): Promise<void> {
|
||||||
const { data, confirm } = event;
|
const { data, confirm } = event;
|
||||||
|
|
||||||
const source = window.textsecure.storage.user.getNumber();
|
const source = window.textsecure.storage.user.getNumber();
|
||||||
const sourceUuid = window.textsecure.storage.user.getAci();
|
const sourceServiceId = window.textsecure.storage.user.getAci();
|
||||||
strictAssert(source && sourceUuid, 'Missing user number and uuid');
|
strictAssert(source && sourceServiceId, 'Missing user number and uuid');
|
||||||
|
|
||||||
const messageDescriptor = getMessageDescriptor({
|
const messageDescriptor = getMessageDescriptor({
|
||||||
...data,
|
...data,
|
||||||
|
@ -2804,7 +2804,7 @@ export async function startApp(): Promise<void> {
|
||||||
remove: reaction.remove,
|
remove: reaction.remove,
|
||||||
source: ReactionSource.FromSync,
|
source: ReactionSource.FromSync,
|
||||||
storyReactionMessage: message,
|
storyReactionMessage: message,
|
||||||
targetAuthorUuid: targetAuthorAci,
|
targetAuthorAci,
|
||||||
targetTimestamp: reaction.targetTimestamp,
|
targetTimestamp: reaction.targetTimestamp,
|
||||||
timestamp,
|
timestamp,
|
||||||
};
|
};
|
||||||
|
@ -2900,7 +2900,7 @@ export async function startApp(): Promise<void> {
|
||||||
serverTimestamp: data.serverTimestamp,
|
serverTimestamp: data.serverTimestamp,
|
||||||
source: data.source,
|
source: data.source,
|
||||||
sourceDevice: data.sourceDevice,
|
sourceDevice: data.sourceDevice,
|
||||||
sourceUuid: data.sourceAci,
|
sourceServiceId: data.sourceAci,
|
||||||
timestamp: data.timestamp,
|
timestamp: data.timestamp,
|
||||||
type: data.message.isStory ? 'story' : 'incoming',
|
type: data.message.isStory ? 'story' : 'incoming',
|
||||||
unidentifiedDeliveryReceived: data.unidentifiedDeliveryReceived,
|
unidentifiedDeliveryReceived: data.unidentifiedDeliveryReceived,
|
||||||
|
@ -3174,7 +3174,7 @@ export async function startApp(): Promise<void> {
|
||||||
wasSentEncrypted,
|
wasSentEncrypted,
|
||||||
} = event.receipt;
|
} = event.receipt;
|
||||||
const sourceConversation = window.ConversationController.lookupOrCreate({
|
const sourceConversation = window.ConversationController.lookupOrCreate({
|
||||||
uuid: sourceServiceId,
|
serviceId: sourceServiceId,
|
||||||
e164: source,
|
e164: source,
|
||||||
reason: `onReadOrViewReceipt(${envelopeTimestamp})`,
|
reason: `onReadOrViewReceipt(${envelopeTimestamp})`,
|
||||||
});
|
});
|
||||||
|
@ -3305,7 +3305,7 @@ export async function startApp(): Promise<void> {
|
||||||
ev.confirm();
|
ev.confirm();
|
||||||
|
|
||||||
const sourceConversation = window.ConversationController.lookupOrCreate({
|
const sourceConversation = window.ConversationController.lookupOrCreate({
|
||||||
uuid: sourceServiceId,
|
serviceId: sourceServiceId,
|
||||||
e164: source,
|
e164: source,
|
||||||
reason: `onDeliveryReceipt(${envelopeTimestamp})`,
|
reason: `onDeliveryReceipt(${envelopeTimestamp})`,
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { SizeObserver } from '../hooks/useSizeObserver';
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
theme: ThemeType;
|
theme: ThemeType;
|
||||||
contact: Pick<ConversationType, 'id' | 'title' | 'uuid'>;
|
contact: Pick<ConversationType, 'id' | 'title' | 'serviceId' | 'pni'>;
|
||||||
candidateConversations: ReadonlyArray<ConversationType>;
|
candidateConversations: ReadonlyArray<ConversationType>;
|
||||||
regionCode: string | undefined;
|
regionCode: string | undefined;
|
||||||
};
|
};
|
||||||
|
@ -119,11 +119,12 @@ export function AddUserToAnotherGroupModal({
|
||||||
|
|
||||||
let disabledReason;
|
let disabledReason;
|
||||||
|
|
||||||
if (memberships.some(c => c.uuid === contact.uuid)) {
|
if (memberships.some(c => c.aci === contact.serviceId)) {
|
||||||
disabledReason = DisabledReason.AlreadyMember;
|
disabledReason = DisabledReason.AlreadyMember;
|
||||||
} else if (
|
} else if (
|
||||||
pendingApprovalMemberships.some(c => c.uuid === contact.uuid) ||
|
pendingApprovalMemberships.some(c => c.aci === contact.serviceId) ||
|
||||||
pendingMemberships.some(c => c.uuid === contact.uuid)
|
pendingMemberships.some(c => c.serviceId === contact.serviceId) ||
|
||||||
|
pendingMemberships.some(c => c.serviceId === contact.pni)
|
||||||
) {
|
) {
|
||||||
disabledReason = DisabledReason.Pending;
|
disabledReason = DisabledReason.Pending;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
),
|
),
|
||||||
title: text('Caller Title', 'Morty Smith'),
|
title: text('Caller Title', 'Morty Smith'),
|
||||||
}),
|
}),
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
},
|
},
|
||||||
notifyForCall: action('notify-for-call'),
|
notifyForCall: action('notify-for-call'),
|
||||||
openSystemPreferencesAction: action('open-system-preferences-action'),
|
openSystemPreferencesAction: action('open-system-preferences-action'),
|
||||||
|
|
|
@ -274,7 +274,7 @@ function ActiveCallManager({
|
||||||
<CallingParticipantsList
|
<CallingParticipantsList
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onClose={toggleParticipants}
|
onClose={toggleParticipants}
|
||||||
ourUuid={me.uuid}
|
ourServiceId={me.serviceId}
|
||||||
participants={peekedParticipants}
|
participants={peekedParticipants}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -359,7 +359,7 @@ function ActiveCallManager({
|
||||||
<CallingParticipantsList
|
<CallingParticipantsList
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onClose={toggleParticipants}
|
onClose={toggleParticipants}
|
||||||
ourUuid={me.uuid}
|
ourServiceId={me.serviceId}
|
||||||
participants={groupCallParticipantsForParticipantsList}
|
participants={groupCallParticipantsForParticipantsList}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { setupI18n } from '../util/setupI18n';
|
||||||
import { missingCaseError } from '../util/missingCaseError';
|
import { missingCaseError } from '../util/missingCaseError';
|
||||||
import {
|
import {
|
||||||
getDefaultConversation,
|
getDefaultConversation,
|
||||||
getDefaultConversationWithUuid,
|
getDefaultConversationWithServiceId,
|
||||||
} from '../test-both/helpers/getDefaultConversation';
|
} from '../test-both/helpers/getDefaultConversation';
|
||||||
import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
|
import { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -175,7 +175,7 @@ const createProps = (
|
||||||
name: 'Morty Smith',
|
name: 'Morty Smith',
|
||||||
profileName: 'Morty Smith',
|
profileName: 'Morty Smith',
|
||||||
title: 'Morty Smith',
|
title: 'Morty Smith',
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
}),
|
}),
|
||||||
openSystemPreferencesAction: action('open-system-preferences-action'),
|
openSystemPreferencesAction: action('open-system-preferences-action'),
|
||||||
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
setGroupCallVideoRequest: action('set-group-call-video-request'),
|
||||||
|
@ -312,7 +312,7 @@ export function GroupCall1(): JSX.Element {
|
||||||
videoAspectRatio: 1.3,
|
videoAspectRatio: 1.3,
|
||||||
...getDefaultConversation({
|
...getDefaultConversation({
|
||||||
isBlocked: false,
|
isBlocked: false,
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
title: 'Tyler',
|
title: 'Tyler',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
@ -334,7 +334,7 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
||||||
presenting: false,
|
presenting: false,
|
||||||
sharingScreen: false,
|
sharingScreen: false,
|
||||||
videoAspectRatio: 1.3,
|
videoAspectRatio: 1.3,
|
||||||
...getDefaultConversationWithUuid({
|
...getDefaultConversationWithServiceId({
|
||||||
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
||||||
title: `Participant ${index + 1}`,
|
title: `Participant ${index + 1}`,
|
||||||
}),
|
}),
|
||||||
|
@ -380,7 +380,7 @@ export function GroupCallReconnecting(): JSX.Element {
|
||||||
...getDefaultConversation({
|
...getDefaultConversation({
|
||||||
isBlocked: false,
|
isBlocked: false,
|
||||||
title: 'Tyler',
|
title: 'Tyler',
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { generateAci } from '../types/ServiceId';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
import {
|
import {
|
||||||
getDefaultConversation,
|
getDefaultConversation,
|
||||||
getDefaultConversationWithUuid,
|
getDefaultConversationWithServiceId,
|
||||||
} from '../test-both/helpers/getDefaultConversation';
|
} from '../test-both/helpers/getDefaultConversation';
|
||||||
|
|
||||||
const i18n = setupI18n('en', enMessages);
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
@ -67,7 +67,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
getDefaultConversation({
|
getDefaultConversation({
|
||||||
color: AvatarColors[0],
|
color: AvatarColors[0],
|
||||||
id: generateUuid(),
|
id: generateUuid(),
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
}),
|
}),
|
||||||
onCallCanceled: action('on-call-canceled'),
|
onCallCanceled: action('on-call-canceled'),
|
||||||
onJoinCall: action('on-join-call'),
|
onJoinCall: action('on-join-call'),
|
||||||
|
@ -87,7 +87,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const fakePeekedParticipant = (conversationProps: Partial<ConversationType>) =>
|
const fakePeekedParticipant = (conversationProps: Partial<ConversationType>) =>
|
||||||
getDefaultConversationWithUuid({
|
getDefaultConversationWithServiceId({
|
||||||
...conversationProps,
|
...conversationProps,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ export function NoCameraLocalAvatar(): JSX.Element {
|
||||||
avatarPath: '/fixtures/kitten-4-112-112.jpg',
|
avatarPath: '/fixtures/kitten-4-112-112.jpg',
|
||||||
color: AvatarColors[0],
|
color: AvatarColors[0],
|
||||||
id: generateUuid(),
|
id: generateUuid(),
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
|
@ -168,14 +168,14 @@ GroupCall1PeekedParticipant.story = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
export function GroupCall1PeekedParticipantSelf(): JSX.Element {
|
||||||
const uuid = generateAci();
|
const serviceId = generateAci();
|
||||||
const props = createProps({
|
const props = createProps({
|
||||||
isGroupCall: true,
|
isGroupCall: true,
|
||||||
me: getDefaultConversation({
|
me: getDefaultConversation({
|
||||||
id: generateUuid(),
|
id: generateUuid(),
|
||||||
uuid,
|
serviceId,
|
||||||
}),
|
}),
|
||||||
peekedParticipants: [fakePeekedParticipant({ title: 'Ash', uuid })],
|
peekedParticipants: [fakePeekedParticipant({ title: 'Ash', serviceId })],
|
||||||
});
|
});
|
||||||
return <CallingLobby {...props} />;
|
return <CallingLobby {...props} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,9 @@ export type PropsType = {
|
||||||
isGroupCall: boolean;
|
isGroupCall: boolean;
|
||||||
isGroupCallOutboundRingEnabled: boolean;
|
isGroupCallOutboundRingEnabled: boolean;
|
||||||
isCallFull?: boolean;
|
isCallFull?: boolean;
|
||||||
me: Readonly<Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'uuid'>>;
|
me: Readonly<
|
||||||
|
Pick<ConversationType, 'avatarPath' | 'color' | 'id' | 'serviceId'>
|
||||||
|
>;
|
||||||
onCallCanceled: () => void;
|
onCallCanceled: () => void;
|
||||||
onJoinCall: () => void;
|
onJoinCall: () => void;
|
||||||
outgoingRing: boolean;
|
outgoingRing: boolean;
|
||||||
|
|
|
@ -9,7 +9,8 @@ import type { PropsType } from './CallingParticipantsList';
|
||||||
import { CallingParticipantsList } from './CallingParticipantsList';
|
import { CallingParticipantsList } from './CallingParticipantsList';
|
||||||
import { AvatarColors } from '../types/Colors';
|
import { AvatarColors } from '../types/Colors';
|
||||||
import type { GroupCallRemoteParticipantType } from '../types/Calling';
|
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 { setupI18n } from '../util/setupI18n';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
@ -25,7 +26,7 @@ function createParticipant(
|
||||||
presenting: Boolean(participantProps.presenting),
|
presenting: Boolean(participantProps.presenting),
|
||||||
sharingScreen: Boolean(participantProps.sharingScreen),
|
sharingScreen: Boolean(participantProps.sharingScreen),
|
||||||
videoAspectRatio: 1.3,
|
videoAspectRatio: 1.3,
|
||||||
...getDefaultConversationWithUuid({
|
...getDefaultConversationWithServiceId({
|
||||||
avatarPath: participantProps.avatarPath,
|
avatarPath: participantProps.avatarPath,
|
||||||
color: sample(AvatarColors),
|
color: sample(AvatarColors),
|
||||||
isBlocked: Boolean(participantProps.isBlocked),
|
isBlocked: Boolean(participantProps.isBlocked),
|
||||||
|
@ -39,7 +40,7 @@ function createParticipant(
|
||||||
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
i18n,
|
i18n,
|
||||||
onClose: action('on-close'),
|
onClose: action('on-close'),
|
||||||
ourUuid: 'cf085e6a-e70b-41ec-a310-c198248af13f',
|
ourServiceId: generateAci(),
|
||||||
participants: overrideProps.participants || [],
|
participants: overrideProps.participants || [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { Avatar, AvatarSize } from './Avatar';
|
||||||
import { ContactName } from './conversation/ContactName';
|
import { ContactName } from './conversation/ContactName';
|
||||||
import { InContactsIcon } from './InContactsIcon';
|
import { InContactsIcon } from './InContactsIcon';
|
||||||
import type { LocalizerType } from '../types/Util';
|
import type { LocalizerType } from '../types/Util';
|
||||||
|
import type { ServiceIdString } from '../types/ServiceId';
|
||||||
import { sortByTitle } from '../util/sortByTitle';
|
import { sortByTitle } from '../util/sortByTitle';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import { isInSystemContacts } from '../util/isInSystemContacts';
|
import { isInSystemContacts } from '../util/isInSystemContacts';
|
||||||
|
@ -25,7 +26,7 @@ type ParticipantType = ConversationType & {
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
readonly i18n: LocalizerType;
|
readonly i18n: LocalizerType;
|
||||||
readonly onClose: () => void;
|
readonly onClose: () => void;
|
||||||
readonly ourUuid: string | undefined;
|
readonly ourServiceId: ServiceIdString | undefined;
|
||||||
readonly participants: Array<ParticipantType>;
|
readonly participants: Array<ParticipantType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ export const CallingParticipantsList = React.memo(
|
||||||
function CallingParticipantsListInner({
|
function CallingParticipantsListInner({
|
||||||
i18n,
|
i18n,
|
||||||
onClose,
|
onClose,
|
||||||
ourUuid,
|
ourServiceId,
|
||||||
participants,
|
participants,
|
||||||
}: PropsType) {
|
}: PropsType) {
|
||||||
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
const [root, setRoot] = React.useState<HTMLElement | null>(null);
|
||||||
|
@ -101,9 +102,9 @@ export const CallingParticipantsList = React.memo(
|
||||||
(participant: ParticipantType, index: number) => (
|
(participant: ParticipantType, index: number) => (
|
||||||
<li
|
<li
|
||||||
className="module-calling-participants-list__contact"
|
className="module-calling-participants-list__contact"
|
||||||
// It's tempting to use `participant.uuid` as the `key` here, but that
|
// It's tempting to use `participant.serviceId` as the `key`
|
||||||
// can result in duplicate keys for participants who have joined on
|
// here, but that can result in duplicate keys for
|
||||||
// multiple devices.
|
// participants who have joined on multiple devices.
|
||||||
key={index}
|
key={index}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
@ -122,7 +123,8 @@ export const CallingParticipantsList = React.memo(
|
||||||
sharedGroupNames={participant.sharedGroupNames}
|
sharedGroupNames={participant.sharedGroupNames}
|
||||||
size={AvatarSize.THIRTY_TWO}
|
size={AvatarSize.THIRTY_TWO}
|
||||||
/>
|
/>
|
||||||
{ourUuid && participant.uuid === ourUuid ? (
|
{ourServiceId &&
|
||||||
|
participant.serviceId === ourServiceId ? (
|
||||||
<span className="module-calling-participants-list__name">
|
<span className="module-calling-participants-list__name">
|
||||||
{i18n('icu:you')}
|
{i18n('icu:you')}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -30,14 +30,14 @@ type PropsType = {
|
||||||
| 'unblurredAvatarPath'
|
| 'unblurredAvatarPath'
|
||||||
>;
|
>;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
me: Pick<ConversationType, 'id' | 'uuid'>;
|
me: Pick<ConversationType, 'id' | 'serviceId'>;
|
||||||
ringMode: RingMode;
|
ringMode: RingMode;
|
||||||
|
|
||||||
// The following should only be set for group conversations.
|
// The following should only be set for group conversations.
|
||||||
groupMembers?: Array<Pick<ConversationType, 'id' | 'firstName' | 'title'>>;
|
groupMembers?: Array<Pick<ConversationType, 'id' | 'firstName' | 'title'>>;
|
||||||
isCallFull?: boolean;
|
isCallFull?: boolean;
|
||||||
peekedParticipants?: Array<
|
peekedParticipants?: Array<
|
||||||
Pick<ConversationType, 'firstName' | 'title' | 'uuid'>
|
Pick<ConversationType, 'firstName' | 'title' | 'serviceId'>
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ export function CallingPreCallInfo({
|
||||||
// device.
|
// device.
|
||||||
let hasYou = false;
|
let hasYou = false;
|
||||||
const participantNames = peekedParticipants.map(participant => {
|
const participantNames = peekedParticipants.map(participant => {
|
||||||
if (participant.uuid === me.uuid) {
|
if (participant.serviceId === me.serviceId) {
|
||||||
hasYou = true;
|
hasYou = true;
|
||||||
return i18n('icu:you');
|
return i18n('icu:you');
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import type {
|
||||||
InMemoryAttachmentDraftType,
|
InMemoryAttachmentDraftType,
|
||||||
} from '../types/Attachment';
|
} from '../types/Attachment';
|
||||||
import { isImageAttachment, isVoiceMessage } from '../types/Attachment';
|
import { isImageAttachment, isVoiceMessage } from '../types/Attachment';
|
||||||
|
import type { AciString } from '../types/ServiceId';
|
||||||
import { AudioCapture } from './conversation/AudioCapture';
|
import { AudioCapture } from './conversation/AudioCapture';
|
||||||
import { CompositionUpload } from './CompositionUpload';
|
import { CompositionUpload } from './CompositionUpload';
|
||||||
import type {
|
import type {
|
||||||
|
@ -87,7 +88,6 @@ export type OwnProps = Readonly<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
discardEditMessage: (id: string) => unknown;
|
discardEditMessage: (id: string) => unknown;
|
||||||
draftEditMessage?: DraftEditMessageType;
|
draftEditMessage?: DraftEditMessageType;
|
||||||
uuid?: string;
|
|
||||||
draftAttachments: ReadonlyArray<AttachmentDraftType>;
|
draftAttachments: ReadonlyArray<AttachmentDraftType>;
|
||||||
errorDialogAudioRecorderType?: ErrorDialogAudioRecorderType;
|
errorDialogAudioRecorderType?: ErrorDialogAudioRecorderType;
|
||||||
errorRecording: (e: ErrorDialogAudioRecorderType) => unknown;
|
errorRecording: (e: ErrorDialogAudioRecorderType) => unknown;
|
||||||
|
@ -131,7 +131,7 @@ export type OwnProps = Readonly<{
|
||||||
options: {
|
options: {
|
||||||
bodyRanges?: DraftBodyRanges;
|
bodyRanges?: DraftBodyRanges;
|
||||||
message?: string;
|
message?: string;
|
||||||
quoteAuthorUuid?: string;
|
quoteAuthorAci?: AciString;
|
||||||
quoteSentAt?: number;
|
quoteSentAt?: number;
|
||||||
targetMessageId: string;
|
targetMessageId: string;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ export type OwnProps = Readonly<{
|
||||||
'i18n' | 'onClick' | 'onClose' | 'withContentAbove' | 'isCompose'
|
'i18n' | 'onClick' | 'onClose' | 'withContentAbove' | 'isCompose'
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
quotedMessageAuthorUuid?: string;
|
quotedMessageAuthorAci?: AciString;
|
||||||
quotedMessageSentAt?: number;
|
quotedMessageSentAt?: number;
|
||||||
|
|
||||||
removeAttachment: (conversationId: string, filePath: string) => unknown;
|
removeAttachment: (conversationId: string, filePath: string) => unknown;
|
||||||
|
@ -256,7 +256,7 @@ export function CompositionArea({
|
||||||
// Quote
|
// Quote
|
||||||
quotedMessageId,
|
quotedMessageId,
|
||||||
quotedMessageProps,
|
quotedMessageProps,
|
||||||
quotedMessageAuthorUuid,
|
quotedMessageAuthorAci,
|
||||||
quotedMessageSentAt,
|
quotedMessageSentAt,
|
||||||
scrollToMessage,
|
scrollToMessage,
|
||||||
// MediaQualitySelector
|
// MediaQualitySelector
|
||||||
|
@ -356,7 +356,7 @@ export function CompositionArea({
|
||||||
message,
|
message,
|
||||||
// sent timestamp for the quote
|
// sent timestamp for the quote
|
||||||
quoteSentAt: quotedMessageSentAt,
|
quoteSentAt: quotedMessageSentAt,
|
||||||
quoteAuthorUuid: quotedMessageAuthorUuid,
|
quoteAuthorAci: quotedMessageAuthorAci,
|
||||||
targetMessageId: editedMessageId,
|
targetMessageId: editedMessageId,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -374,7 +374,7 @@ export function CompositionArea({
|
||||||
draftAttachments,
|
draftAttachments,
|
||||||
editedMessageId,
|
editedMessageId,
|
||||||
quotedMessageSentAt,
|
quotedMessageSentAt,
|
||||||
quotedMessageAuthorUuid,
|
quotedMessageAuthorAci,
|
||||||
sendEditedMessage,
|
sendEditedMessage,
|
||||||
sendMultiMediaMessage,
|
sendMultiMediaMessage,
|
||||||
setLarge,
|
setLarge,
|
||||||
|
|
|
@ -138,7 +138,7 @@ export function Mentions(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 5,
|
start: 5,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: generateAci(),
|
mentionAci: generateAci(),
|
||||||
conversationID: 'k',
|
conversationID: 'k',
|
||||||
replacementText: 'Kate Beaton',
|
replacementText: 'Kate Beaton',
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { BodyRange, collapseRangeTree, insertRange } from '../types/BodyRange';
|
||||||
import type { LocalizerType, ThemeType } from '../types/Util';
|
import type { LocalizerType, ThemeType } from '../types/Util';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
import type { PreferredBadgeSelectorType } from '../state/selectors/badges';
|
||||||
import { isServiceIdString } from '../types/ServiceId';
|
import { isAciString } from '../types/ServiceId';
|
||||||
import { MentionBlot } from '../quill/mentions/blot';
|
import { MentionBlot } from '../quill/mentions/blot';
|
||||||
import {
|
import {
|
||||||
matchEmojiImage,
|
matchEmojiImage,
|
||||||
|
@ -678,15 +678,12 @@ export function CompositionInput(props: Props): React.ReactElement {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentMemberServiceIds = currentMembers
|
const currentMemberAcis = currentMembers
|
||||||
.map(m => m.uuid)
|
.map(m => m.serviceId)
|
||||||
.filter(isNotNil)
|
.filter(isNotNil)
|
||||||
.filter(isServiceIdString);
|
.filter(isAciString);
|
||||||
|
|
||||||
const newDelta = getDeltaToRemoveStaleMentions(
|
const newDelta = getDeltaToRemoveStaleMentions(ops, currentMemberAcis);
|
||||||
ops,
|
|
||||||
currentMemberServiceIds
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
quill.updateContents(newDelta as any);
|
quill.updateContents(newDelta as any);
|
||||||
|
|
|
@ -374,7 +374,7 @@ export function ConversationList({
|
||||||
'unblurredAvatarPath',
|
'unblurredAvatarPath',
|
||||||
'unreadCount',
|
'unreadCount',
|
||||||
'unreadMentionsCount',
|
'unreadMentionsCount',
|
||||||
'uuid',
|
'serviceId',
|
||||||
]);
|
]);
|
||||||
const { badges, title, unreadCount, lastMessage } = itemProps;
|
const { badges, title, unreadCount, lastMessage } = itemProps;
|
||||||
result = (
|
result = (
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { action } from '@storybook/addon-actions';
|
||||||
|
|
||||||
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
import { GroupCallOverflowArea } from './GroupCallOverflowArea';
|
||||||
import { setupI18n } from '../util/setupI18n';
|
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 { fakeGetGroupCallVideoFrameSource } from '../test-both/helpers/fakeGetGroupCallVideoFrameSource';
|
||||||
import { FRAME_BUFFER_SIZE } from '../calling/constants';
|
import { FRAME_BUFFER_SIZE } from '../calling/constants';
|
||||||
import enMessages from '../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
@ -24,7 +24,7 @@ const allRemoteParticipants = times(MAX_PARTICIPANTS).map(index => ({
|
||||||
presenting: false,
|
presenting: false,
|
||||||
sharingScreen: false,
|
sharingScreen: false,
|
||||||
videoAspectRatio: 1.3,
|
videoAspectRatio: 1.3,
|
||||||
...getDefaultConversationWithUuid({
|
...getDefaultConversationWithServiceId({
|
||||||
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
isBlocked: index === 10 || index === MAX_PARTICIPANTS - 1,
|
||||||
title: `Participant ${index + 1}`,
|
title: `Participant ${index + 1}`,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -61,7 +61,7 @@ const createProps = (
|
||||||
isBlocked: Boolean(isBlocked),
|
isBlocked: Boolean(isBlocked),
|
||||||
title:
|
title:
|
||||||
'Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso',
|
'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,
|
remoteParticipantsCount: 1,
|
||||||
|
|
|
@ -310,7 +310,9 @@ function ContactSection({
|
||||||
}
|
}
|
||||||
|
|
||||||
const { distributionId } = section.story;
|
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 =
|
const sectionName =
|
||||||
distributionId === MY_STORY_ID
|
distributionId === MY_STORY_ID
|
||||||
? i18n('icu:Stories__mine')
|
? i18n('icu:Stories__mine')
|
||||||
|
@ -322,17 +324,17 @@ function ContactSection({
|
||||||
<div className="module-SafetyNumberChangeDialog__row__story-name">
|
<div className="module-SafetyNumberChangeDialog__row__story-name">
|
||||||
{sectionName}
|
{sectionName}
|
||||||
</div>
|
</div>
|
||||||
{distributionId && removeFromStory && uuids.length > 1 && (
|
{distributionId && removeFromStory && serviceIds.length > 1 && (
|
||||||
<SectionButtonWithMenu
|
<SectionButtonWithMenu
|
||||||
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-story', {
|
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-story', {
|
||||||
story: sectionName,
|
story: sectionName,
|
||||||
})}
|
})}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
memberCount={uuids.length}
|
memberCount={serviceIds.length}
|
||||||
storyName={sectionName}
|
storyName={sectionName}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
removeFromStory={() => {
|
removeFromStory={() => {
|
||||||
removeFromStory(distributionId, uuids);
|
removeFromStory(distributionId, serviceIds);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -443,7 +445,7 @@ function ContactRow({
|
||||||
shouldShowNumber: boolean;
|
shouldShowNumber: boolean;
|
||||||
theme: ThemeType;
|
theme: ThemeType;
|
||||||
}>) {
|
}>) {
|
||||||
const { uuid } = contact;
|
const { serviceId } = contact;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="module-SafetyNumberChangeDialog__row" key={contact.id}>
|
<li className="module-SafetyNumberChangeDialog__row" key={contact.id}>
|
||||||
|
@ -493,14 +495,14 @@ function ContactRow({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{distributionId && removeFromStory && uuid ? (
|
{distributionId && removeFromStory && serviceId ? (
|
||||||
<RowButtonWithMenu
|
<RowButtonWithMenu
|
||||||
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-contact', {
|
ariaLabel={i18n('icu:safetyNumberChangeDialog__actions-contact', {
|
||||||
contact: contact.title,
|
contact: contact.title,
|
||||||
})}
|
})}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
removeFromStory={() => removeFromStory(distributionId, [uuid])}
|
removeFromStory={() => removeFromStory(distributionId, [serviceId])}
|
||||||
verifyContact={() => setSelectedContact(contact)}
|
verifyContact={() => setSelectedContact(contact)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -59,7 +59,7 @@ export type PropsType = {
|
||||||
onDeleteList: (listId: StoryDistributionIdString) => unknown;
|
onDeleteList: (listId: StoryDistributionIdString) => unknown;
|
||||||
onDistributionListCreated: (
|
onDistributionListCreated: (
|
||||||
name: string,
|
name: string,
|
||||||
viewerUuids: Array<ServiceIdString>
|
viewerServiceIds: Array<ServiceIdString>
|
||||||
) => Promise<StoryDistributionIdString>;
|
) => Promise<StoryDistributionIdString>;
|
||||||
onSelectedStoryList: (options: {
|
onSelectedStoryList: (options: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -107,15 +107,15 @@ function getListMemberServiceIds(
|
||||||
signalConnections: Array<ConversationType>
|
signalConnections: Array<ConversationType>
|
||||||
): Array<ServiceIdString> {
|
): Array<ServiceIdString> {
|
||||||
const memberServiceIds = list.members
|
const memberServiceIds = list.members
|
||||||
.map(({ uuid }) => uuid)
|
.map(({ serviceId }) => serviceId)
|
||||||
.filter(isNotNil);
|
.filter(isNotNil);
|
||||||
|
|
||||||
if (list.id === MY_STORY_ID && list.isBlockList) {
|
if (list.id === MY_STORY_ID && list.isBlockList) {
|
||||||
const excludeUuids = new Set<string>(memberServiceIds);
|
const excludeServiceIds = new Set<ServiceIdString>(memberServiceIds);
|
||||||
return signalConnections
|
return signalConnections
|
||||||
.map(conversation => conversation.uuid)
|
.map(conversation => conversation.serviceId)
|
||||||
.filter(isNotNil)
|
.filter(isNotNil)
|
||||||
.filter(uuid => !excludeUuids.has(uuid));
|
.filter(serviceId => !excludeServiceIds.has(serviceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
return memberServiceIds;
|
return memberServiceIds;
|
||||||
|
@ -242,7 +242,7 @@ export function SendStoryModal({
|
||||||
return distributionLists.find(list => list.id === listIdToEdit);
|
return distributionLists.find(list => list.id === listIdToEdit);
|
||||||
}, [distributionLists, 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
|
// during the first time posting to My Stories experience where we have
|
||||||
// to select the privacy settings.
|
// to select the privacy settings.
|
||||||
const ogMyStories = useMemo(
|
const ogMyStories = useMemo(
|
||||||
|
@ -310,18 +310,18 @@ export function SendStoryModal({
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const uuids = stagedMyStories.members
|
const serviceIds = stagedMyStories.members
|
||||||
.map(convo => convo.uuid)
|
.map(convo => convo.serviceId)
|
||||||
.filter(isNotNil);
|
.filter(isNotNil);
|
||||||
|
|
||||||
if (stagedMyStories.isBlockList) {
|
if (stagedMyStories.isBlockList) {
|
||||||
if (stagedMyStories.members.length) {
|
if (stagedMyStories.members.length) {
|
||||||
onHideMyStoriesFrom(uuids);
|
onHideMyStoriesFrom(serviceIds);
|
||||||
} else {
|
} else {
|
||||||
setMyStoriesToAllSignalConnections();
|
setMyStoriesToAllSignalConnections();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onViewersUpdated(MY_STORY_ID, uuids);
|
onViewersUpdated(MY_STORY_ID, serviceIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedContacts([]);
|
setSelectedContacts([]);
|
||||||
|
@ -425,10 +425,10 @@ export function SendStoryModal({
|
||||||
candidateConversations={candidateConversations}
|
candidateConversations={candidateConversations}
|
||||||
getPreferredBadge={getPreferredBadge}
|
getPreferredBadge={getPreferredBadge}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onCreateList={async (name, uuids) => {
|
onCreateList={async (name, serviceIds) => {
|
||||||
const newDistributionListId = await onDistributionListCreated(
|
const newDistributionListId = await onDistributionListCreated(
|
||||||
name,
|
name,
|
||||||
uuids
|
serviceIds
|
||||||
);
|
);
|
||||||
|
|
||||||
setSelectedContacts([]);
|
setSelectedContacts([]);
|
||||||
|
@ -438,19 +438,19 @@ export function SendStoryModal({
|
||||||
|
|
||||||
setPage(Page.SendStory);
|
setPage(Page.SendStory);
|
||||||
}}
|
}}
|
||||||
onViewersUpdated={uuids => {
|
onViewersUpdated={serviceIds => {
|
||||||
if (listIdToEdit && page === Page.AddViewer) {
|
if (listIdToEdit && page === Page.AddViewer) {
|
||||||
onViewersUpdated(listIdToEdit, uuids);
|
onViewersUpdated(listIdToEdit, serviceIds);
|
||||||
setPage(Page.EditingDistributionList);
|
setPage(Page.EditingDistributionList);
|
||||||
} else if (page === Page.ChooseViewers) {
|
} else if (page === Page.ChooseViewers) {
|
||||||
setPage(Page.NameStory);
|
setPage(Page.NameStory);
|
||||||
} else if (listIdToEdit && page === Page.HideStoryFrom) {
|
} else if (listIdToEdit && page === Page.HideStoryFrom) {
|
||||||
onHideMyStoriesFrom(uuids);
|
onHideMyStoriesFrom(serviceIds);
|
||||||
setPage(Page.SendStory);
|
setPage(Page.SendStory);
|
||||||
} else if (page === Page.HideStoryFrom || page === Page.AddViewer) {
|
} else if (page === Page.HideStoryFrom || page === Page.AddViewer) {
|
||||||
const uuidsSet = new Set(uuids);
|
const serviceIdSet = new Set(serviceIds);
|
||||||
const members = candidateConversations.filter(convo =>
|
const members = candidateConversations.filter(convo =>
|
||||||
convo.uuid ? uuidsSet.has(convo.uuid) : false
|
convo.serviceId ? serviceIdSet.has(convo.serviceId) : false
|
||||||
);
|
);
|
||||||
setStagedMyStories(myStories => ({
|
setStagedMyStories(myStories => ({
|
||||||
...myStories,
|
...myStories,
|
||||||
|
@ -800,7 +800,7 @@ export function SendStoryModal({
|
||||||
onSelectedStoryList({
|
onSelectedStoryList({
|
||||||
conversationId: group.id,
|
conversationId: group.id,
|
||||||
distributionId: undefined,
|
distributionId: undefined,
|
||||||
serviceIds: group.memberships.map(({ uuid }) => uuid),
|
serviceIds: group.memberships.map(({ aci }) => aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -54,7 +54,7 @@ export default {
|
||||||
setMyStoriesToAllSignalConnections: { action: true },
|
setMyStoriesToAllSignalConnections: { action: true },
|
||||||
toggleSignalConnectionsModal: { action: true },
|
toggleSignalConnectionsModal: { action: true },
|
||||||
setStoriesDisabled: { action: true },
|
setStoriesDisabled: { action: true },
|
||||||
getConversationByUuid: {
|
getConversationByServiceId: {
|
||||||
defaultValue: () => getDefaultGroup(),
|
defaultValue: () => getDefaultGroup(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -52,25 +52,28 @@ export type PropsType = {
|
||||||
toggleGroupsForStorySend: (groupIds: Array<string>) => unknown;
|
toggleGroupsForStorySend: (groupIds: Array<string>) => unknown;
|
||||||
onDistributionListCreated: (
|
onDistributionListCreated: (
|
||||||
name: string,
|
name: string,
|
||||||
viewerUuids: Array<ServiceIdString>
|
viewerServiceIds: Array<ServiceIdString>
|
||||||
) => Promise<string>;
|
) => Promise<string>;
|
||||||
onHideMyStoriesFrom: (viewerUuids: Array<ServiceIdString>) => unknown;
|
onHideMyStoriesFrom: (viewerServiceIds: Array<ServiceIdString>) => unknown;
|
||||||
onRemoveMembers: (listId: string, uuids: Array<ServiceIdString>) => unknown;
|
onRemoveMembers: (
|
||||||
|
listId: string,
|
||||||
|
serviceIds: Array<ServiceIdString>
|
||||||
|
) => unknown;
|
||||||
onRepliesNReactionsChanged: (
|
onRepliesNReactionsChanged: (
|
||||||
listId: string,
|
listId: string,
|
||||||
allowsReplies: boolean
|
allowsReplies: boolean
|
||||||
) => unknown;
|
) => unknown;
|
||||||
onViewersUpdated: (
|
onViewersUpdated: (
|
||||||
listId: string,
|
listId: string,
|
||||||
viewerUuids: Array<ServiceIdString>
|
viewerServiceIds: Array<ServiceIdString>
|
||||||
) => unknown;
|
) => unknown;
|
||||||
setMyStoriesToAllSignalConnections: () => unknown;
|
setMyStoriesToAllSignalConnections: () => unknown;
|
||||||
storyViewReceiptsEnabled: boolean;
|
storyViewReceiptsEnabled: boolean;
|
||||||
theme: ThemeType;
|
theme: ThemeType;
|
||||||
toggleSignalConnectionsModal: () => unknown;
|
toggleSignalConnectionsModal: () => unknown;
|
||||||
setStoriesDisabled: (value: boolean) => void;
|
setStoriesDisabled: (value: boolean) => void;
|
||||||
getConversationByUuid: (
|
getConversationByServiceId: (
|
||||||
uuid: ServiceIdString
|
serviceId: ServiceIdString
|
||||||
) => ConversationType | undefined;
|
) => ConversationType | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +93,7 @@ function filterConversations(
|
||||||
conversations,
|
conversations,
|
||||||
searchTerm,
|
searchTerm,
|
||||||
undefined
|
undefined
|
||||||
).filter(conversation => conversation.uuid);
|
).filter(conversation => conversation.serviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const modalCommonProps: Pick<ModalPropsType, 'hasXButton' | 'moduleClassName'> =
|
const modalCommonProps: Pick<ModalPropsType, 'hasXButton' | 'moduleClassName'> =
|
||||||
|
@ -258,7 +261,7 @@ export function StoriesSettingsModal({
|
||||||
toggleSignalConnectionsModal,
|
toggleSignalConnectionsModal,
|
||||||
theme,
|
theme,
|
||||||
setStoriesDisabled,
|
setStoriesDisabled,
|
||||||
getConversationByUuid,
|
getConversationByServiceId,
|
||||||
}: PropsType): JSX.Element {
|
}: PropsType): JSX.Element {
|
||||||
const [confirmDiscardModal, confirmDiscardIf] = useConfirmDiscard(i18n);
|
const [confirmDiscardModal, confirmDiscardIf] = useConfirmDiscard(i18n);
|
||||||
|
|
||||||
|
@ -311,8 +314,8 @@ export function StoriesSettingsModal({
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
page={page}
|
page={page}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onCreateList={(name, uuids) => {
|
onCreateList={(name, serviceIds) => {
|
||||||
void onDistributionListCreated(name, uuids);
|
void onDistributionListCreated(name, serviceIds);
|
||||||
resetChooseViewersScreen();
|
resetChooseViewersScreen();
|
||||||
}}
|
}}
|
||||||
onBackButtonClick={() =>
|
onBackButtonClick={() =>
|
||||||
|
@ -330,9 +333,9 @@ export function StoriesSettingsModal({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onViewersUpdated={uuids => {
|
onViewersUpdated={serviceIds => {
|
||||||
if (listToEditId && page === Page.AddViewer) {
|
if (listToEditId && page === Page.AddViewer) {
|
||||||
onViewersUpdated(listToEditId, uuids);
|
onViewersUpdated(listToEditId, serviceIds);
|
||||||
resetChooseViewersScreen();
|
resetChooseViewersScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,7 +344,7 @@ export function StoriesSettingsModal({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page === Page.HideStoryFrom) {
|
if (page === Page.HideStoryFrom) {
|
||||||
onHideMyStoriesFrom(uuids);
|
onHideMyStoriesFrom(serviceIds);
|
||||||
resetChooseViewersScreen();
|
resetChooseViewersScreen();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
@ -377,7 +380,7 @@ export function StoriesSettingsModal({
|
||||||
group={groupToView}
|
group={groupToView}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
onBackButtonClick={() => setGroupToViewId(null)}
|
onBackButtonClick={() => setGroupToViewId(null)}
|
||||||
getConversationByUuid={getConversationByUuid}
|
getConversationByServiceId={getConversationByServiceId}
|
||||||
onRemoveGroup={group => {
|
onRemoveGroup={group => {
|
||||||
setConfirmRemoveGroup({
|
setConfirmRemoveGroup({
|
||||||
id: group.id,
|
id: group.id,
|
||||||
|
@ -583,7 +586,7 @@ export function DistributionListSettingsModal({
|
||||||
| {
|
| {
|
||||||
listId: string;
|
listId: string;
|
||||||
title: string;
|
title: string;
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
}
|
}
|
||||||
>();
|
>();
|
||||||
|
|
||||||
|
@ -695,11 +698,14 @@ export function DistributionListSettingsModal({
|
||||||
})}
|
})}
|
||||||
className="StoriesSettingsModal__list__delete"
|
className="StoriesSettingsModal__list__delete"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
strictAssert(member.uuid, 'Story member was missing uuid');
|
strictAssert(
|
||||||
|
member.serviceId,
|
||||||
|
'Story member was missing service id'
|
||||||
|
);
|
||||||
setConfirmRemoveMember({
|
setConfirmRemoveMember({
|
||||||
listId: listToEdit.id,
|
listId: listToEdit.id,
|
||||||
title: member.title,
|
title: member.title,
|
||||||
uuid: member.uuid,
|
serviceId: member.serviceId,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -747,7 +753,7 @@ export function DistributionListSettingsModal({
|
||||||
{
|
{
|
||||||
action: () =>
|
action: () =>
|
||||||
onRemoveMembers(confirmRemoveMember.listId, [
|
onRemoveMembers(confirmRemoveMember.listId, [
|
||||||
confirmRemoveMember.uuid,
|
confirmRemoveMember.serviceId,
|
||||||
]),
|
]),
|
||||||
style: 'negative',
|
style: 'negative',
|
||||||
text: i18n('icu:StoriesSettings__remove--action'),
|
text: i18n('icu:StoriesSettings__remove--action'),
|
||||||
|
@ -950,8 +956,11 @@ export function EditMyStoryPrivacy({
|
||||||
}
|
}
|
||||||
|
|
||||||
type EditDistributionListModalPropsType = {
|
type EditDistributionListModalPropsType = {
|
||||||
onCreateList: (name: string, viewerUuids: Array<ServiceIdString>) => unknown;
|
onCreateList: (
|
||||||
onViewersUpdated: (viewerUuids: Array<ServiceIdString>) => unknown;
|
name: string,
|
||||||
|
viewerServiceIds: Array<ServiceIdString>
|
||||||
|
) => unknown;
|
||||||
|
onViewersUpdated: (viewerServiceIds: Array<ServiceIdString>) => unknown;
|
||||||
page:
|
page:
|
||||||
| Page.AddViewer
|
| Page.AddViewer
|
||||||
| Page.ChooseViewers
|
| Page.ChooseViewers
|
||||||
|
@ -1007,7 +1016,9 @@ export function EditDistributionListModal({
|
||||||
|
|
||||||
const selectConversationServiceIds: Set<ServiceIdString> = useMemo(
|
const selectConversationServiceIds: Set<ServiceIdString> = useMemo(
|
||||||
() =>
|
() =>
|
||||||
new Set(selectedContacts.map(contact => contact.uuid).filter(isNotNil)),
|
new Set(
|
||||||
|
selectedContacts.map(contact => contact.serviceId).filter(isNotNil)
|
||||||
|
),
|
||||||
[selectedContacts]
|
[selectedContacts]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1108,11 +1119,11 @@ export function EditDistributionListModal({
|
||||||
const rowCount = filteredConversations.length;
|
const rowCount = filteredConversations.length;
|
||||||
const getRow = (index: number): undefined | Row => {
|
const getRow = (index: number): undefined | Row => {
|
||||||
const contact = filteredConversations[index];
|
const contact = filteredConversations[index];
|
||||||
if (!contact || !contact.uuid) {
|
if (!contact || !contact.serviceId) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSelected = selectConversationServiceIds.has(contact.uuid);
|
const isSelected = selectConversationServiceIds.has(contact.serviceId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: RowType.ContactCheckbox,
|
type: RowType.ContactCheckbox,
|
||||||
|
@ -1243,7 +1254,9 @@ type GroupStorySettingsModalProps = {
|
||||||
group: ConversationType;
|
group: ConversationType;
|
||||||
onClose(): void;
|
onClose(): void;
|
||||||
onBackButtonClick(): void;
|
onBackButtonClick(): void;
|
||||||
getConversationByUuid(uuid: ServiceIdString): ConversationType | undefined;
|
getConversationByServiceId(
|
||||||
|
serviceId: ServiceIdString
|
||||||
|
): ConversationType | undefined;
|
||||||
onRemoveGroup(group: ConversationType): void;
|
onRemoveGroup(group: ConversationType): void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1252,10 +1265,13 @@ export function GroupStorySettingsModal({
|
||||||
group,
|
group,
|
||||||
onClose,
|
onClose,
|
||||||
onBackButtonClick,
|
onBackButtonClick,
|
||||||
getConversationByUuid,
|
getConversationByServiceId,
|
||||||
onRemoveGroup,
|
onRemoveGroup,
|
||||||
}: GroupStorySettingsModalProps): JSX.Element {
|
}: GroupStorySettingsModalProps): JSX.Element {
|
||||||
const groupMemberships = getGroupMemberships(group, getConversationByUuid);
|
const groupMemberships = getGroupMemberships(
|
||||||
|
group,
|
||||||
|
getConversationByServiceId
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<ModalPage
|
<ModalPage
|
||||||
modalName="GroupStorySettingsModal"
|
modalName="GroupStorySettingsModal"
|
||||||
|
|
|
@ -103,7 +103,7 @@ export function StoryListItem({
|
||||||
|
|
||||||
const { firstName, title } = sender;
|
const { firstName, title } = sender;
|
||||||
|
|
||||||
const isSignalOfficial = sender.uuid === SIGNAL_ACI;
|
const isSignalOfficial = sender.serviceId === SIGNAL_ACI;
|
||||||
|
|
||||||
let avatarStoryRing: HasStories | undefined;
|
let avatarStoryRing: HasStories | undefined;
|
||||||
if (attachment) {
|
if (attachment) {
|
||||||
|
|
|
@ -40,21 +40,21 @@ export function MultipleMentions(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 4,
|
start: 4,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_1,
|
mentionAci: SERVICE_ID_1,
|
||||||
replacementText: 'Professor Farnsworth',
|
replacementText: 'Professor Farnsworth',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 2,
|
start: 2,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_2,
|
mentionAci: SERVICE_ID_2,
|
||||||
replacementText: 'Philip J Fry',
|
replacementText: 'Philip J Fry',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 0,
|
start: 0,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Yancy Fry',
|
replacementText: 'Yancy Fry',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -73,21 +73,21 @@ export function ComplexMentions(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 80,
|
start: 80,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_4,
|
mentionAci: SERVICE_ID_4,
|
||||||
replacementText: 'Cereal Killer',
|
replacementText: 'Cereal Killer',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 78,
|
start: 78,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_5,
|
mentionAci: SERVICE_ID_5,
|
||||||
replacementText: 'Acid Burn',
|
replacementText: 'Acid Burn',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 4,
|
start: 4,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_6,
|
mentionAci: SERVICE_ID_6,
|
||||||
replacementText: 'Zero Cool',
|
replacementText: 'Zero Cool',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -109,7 +109,7 @@ export function WithOddCharacter(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 4,
|
start: 4,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_6,
|
mentionAci: SERVICE_ID_6,
|
||||||
replacementText: 'Zero Cool',
|
replacementText: 'Zero Cool',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,7 +45,7 @@ const getCommonProps = (options: {
|
||||||
? GroupCallStatus.GenericGroupCall
|
? GroupCallStatus.GenericGroupCall
|
||||||
: DirectCallStatus.Pending,
|
: DirectCallStatus.Pending,
|
||||||
callCreator = getDefaultConversation({
|
callCreator = getDefaultConversation({
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
isMe: direction === CallDirection.Outgoing,
|
isMe: direction === CallDirection.Outgoing,
|
||||||
}),
|
}),
|
||||||
callExternalState = CallExternalState.Active,
|
callExternalState = CallExternalState.Active,
|
||||||
|
@ -63,7 +63,7 @@ const getCommonProps = (options: {
|
||||||
callHistory: {
|
callHistory: {
|
||||||
callId: '123',
|
callId: '123',
|
||||||
peerId: conversation.id,
|
peerId: conversation.id,
|
||||||
ringerId: callCreator?.uuid ?? null,
|
ringerId: callCreator?.serviceId ?? null,
|
||||||
mode,
|
mode,
|
||||||
type,
|
type,
|
||||||
direction,
|
direction,
|
||||||
|
|
|
@ -44,7 +44,7 @@ const renderChange = (
|
||||||
areWeAdmin = true,
|
areWeAdmin = true,
|
||||||
}: {
|
}: {
|
||||||
groupMemberships?: ReadonlyArray<{
|
groupMemberships?: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>;
|
}>;
|
||||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||||
|
@ -92,7 +92,7 @@ export function Multiple(): JSX.Element {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'description',
|
type: 'description',
|
||||||
|
@ -100,7 +100,7 @@ export function Multiple(): JSX.Element {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -451,7 +451,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -460,7 +460,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -468,7 +468,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -477,7 +477,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -486,7 +486,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -494,7 +494,7 @@ export function MemberAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add',
|
type: 'member-add',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -511,7 +511,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -520,7 +520,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
inviter: CONTACT_A,
|
inviter: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -531,7 +531,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -541,7 +541,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_B,
|
aci: CONTACT_B,
|
||||||
inviter: CONTACT_C,
|
inviter: CONTACT_C,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -550,7 +550,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -561,7 +561,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
inviter: CONTACT_A,
|
inviter: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -571,7 +571,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -580,7 +580,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
inviter: OUR_ACI,
|
inviter: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -590,7 +590,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -600,7 +600,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -610,7 +610,7 @@ export function MemberAddFromInvited(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-invite',
|
type: 'member-add-from-invite',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -631,7 +631,7 @@ export function MemberAddFromLink(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-link',
|
type: 'member-add-from-link',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -640,7 +640,7 @@ export function MemberAddFromLink(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-link',
|
type: 'member-add-from-link',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -648,7 +648,7 @@ export function MemberAddFromLink(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-link',
|
type: 'member-add-from-link',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -668,7 +668,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-admin-approval',
|
type: 'member-add-from-admin-approval',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -676,7 +676,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-admin-approval',
|
type: 'member-add-from-admin-approval',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -685,7 +685,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-admin-approval',
|
type: 'member-add-from-admin-approval',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -694,7 +694,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-admin-approval',
|
type: 'member-add-from-admin-approval',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -702,7 +702,7 @@ export function MemberAddFromAdminApproval(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-add-from-admin-approval',
|
type: 'member-add-from-admin-approval',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -722,7 +722,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -731,7 +731,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -739,7 +739,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -748,7 +748,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -757,7 +757,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -766,7 +766,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -774,7 +774,7 @@ export function MemberRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-remove',
|
type: 'member-remove',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -790,7 +790,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -799,7 +799,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -809,7 +809,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -819,7 +819,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -828,7 +828,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.ADMINISTRATOR,
|
newPrivilege: RoleEnum.ADMINISTRATOR,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -838,7 +838,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
newPrivilege: RoleEnum.DEFAULT,
|
newPrivilege: RoleEnum.DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -847,7 +847,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
newPrivilege: RoleEnum.DEFAULT,
|
newPrivilege: RoleEnum.DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -857,7 +857,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.DEFAULT,
|
newPrivilege: RoleEnum.DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -867,7 +867,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.DEFAULT,
|
newPrivilege: RoleEnum.DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -876,7 +876,7 @@ export function MemberPrivilege(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'member-privilege',
|
type: 'member-privilege',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
newPrivilege: RoleEnum.DEFAULT,
|
newPrivilege: RoleEnum.DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -893,7 +893,7 @@ export function PendingAddOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-add-one',
|
type: 'pending-add-one',
|
||||||
uuid: OUR_ACI,
|
serviceId: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -901,7 +901,7 @@ export function PendingAddOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-add-one',
|
type: 'pending-add-one',
|
||||||
uuid: OUR_ACI,
|
serviceId: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -910,7 +910,7 @@ export function PendingAddOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-add-one',
|
type: 'pending-add-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -919,7 +919,7 @@ export function PendingAddOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-add-one',
|
type: 'pending-add-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -927,7 +927,7 @@ export function PendingAddOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-add-one',
|
type: 'pending-add-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -984,7 +984,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: OUR_ACI,
|
inviter: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -994,7 +994,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: OUR_ACI,
|
inviter: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1004,7 +1004,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: OUR_ACI,
|
inviter: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1013,7 +1013,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: OUR_ACI,
|
inviter: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1023,7 +1023,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1032,7 +1032,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1043,7 +1043,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: OUR_ACI,
|
serviceId: OUR_ACI,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1053,7 +1053,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: CONTACT_B,
|
serviceId: CONTACT_B,
|
||||||
inviter: CONTACT_A,
|
inviter: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1064,7 +1064,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1074,7 +1074,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1083,7 +1083,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
inviter: CONTACT_B,
|
inviter: CONTACT_B,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1094,7 +1094,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1103,7 +1103,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1111,7 +1111,7 @@ export function PendingRemoveOne(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'pending-remove-one',
|
type: 'pending-remove-one',
|
||||||
uuid: INVITEE_A,
|
serviceId: INVITEE_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1226,7 +1226,7 @@ export function AdminApprovalAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-add-one',
|
type: 'admin-approval-add-one',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1234,7 +1234,7 @@ export function AdminApprovalAdd(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-add-one',
|
type: 'admin-approval-add-one',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1254,7 +1254,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-remove-one',
|
type: 'admin-approval-remove-one',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1262,7 +1262,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-remove-one',
|
type: 'admin-approval-remove-one',
|
||||||
uuid: OUR_ACI,
|
aci: OUR_ACI,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1271,7 +1271,7 @@ export function AdminApprovalRemove(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-remove-one',
|
type: 'admin-approval-remove-one',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})}
|
})}
|
||||||
|
@ -1294,14 +1294,14 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupMemberships: [{ uuid: CONTACT_C, isAdmin: false }],
|
groupMemberships: [{ aci: CONTACT_C, isAdmin: false }],
|
||||||
groupBannedMemberships: [CONTACT_B],
|
groupBannedMemberships: [CONTACT_B],
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
@ -1311,14 +1311,14 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupMemberships: [{ uuid: CONTACT_C, isAdmin: false }],
|
groupMemberships: [{ aci: CONTACT_C, isAdmin: false }],
|
||||||
groupBannedMemberships: [CONTACT_B],
|
groupBannedMemberships: [CONTACT_B],
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
@ -1326,7 +1326,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
|
@ -1340,7 +1340,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
|
@ -1356,13 +1356,13 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ groupMemberships: [{ uuid: CONTACT_A, isAdmin: false }] }
|
{ groupMemberships: [{ aci: CONTACT_A, isAdmin: false }] }
|
||||||
)}
|
)}
|
||||||
Would show button, but user is already banned:
|
Would show button, but user is already banned:
|
||||||
{renderChange(
|
{renderChange(
|
||||||
|
@ -1371,7 +1371,7 @@ export function AdminApprovalBounce(): JSX.Element {
|
||||||
details: [
|
details: [
|
||||||
{
|
{
|
||||||
type: 'admin-approval-bounce',
|
type: 'admin-approval-bounce',
|
||||||
uuid: CONTACT_A,
|
aci: CONTACT_A,
|
||||||
times: 1,
|
times: 1,
|
||||||
isApprovalPending: false,
|
isApprovalPending: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,7 +30,7 @@ export type PropsDataType = {
|
||||||
areWeAdmin: boolean;
|
areWeAdmin: boolean;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
groupMemberships?: ReadonlyArray<{
|
groupMemberships?: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>;
|
}>;
|
||||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||||
|
@ -116,7 +116,7 @@ function getIcon(
|
||||||
): GroupIconType {
|
): GroupIconType {
|
||||||
const changeType = detail.type;
|
const changeType = detail.type;
|
||||||
let possibleIcon = changeToIconMap.get(changeType);
|
let possibleIcon = changeToIconMap.get(changeType);
|
||||||
const isSameId = fromId === get(detail, 'uuid', null);
|
const isSameId = fromId === get(detail, 'aci', null);
|
||||||
if (isSameId) {
|
if (isSameId) {
|
||||||
if (changeType === 'member-remove') {
|
if (changeType === 'member-remove') {
|
||||||
possibleIcon = 'group-leave';
|
possibleIcon = 'group-leave';
|
||||||
|
@ -154,13 +154,13 @@ function GroupV2Detail({
|
||||||
areWeAdmin: boolean;
|
areWeAdmin: boolean;
|
||||||
blockGroupLinkRequests: (
|
blockGroupLinkRequests: (
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
uuid: ServiceIdString
|
serviceId: ServiceIdString
|
||||||
) => unknown;
|
) => unknown;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
detail: GroupV2ChangeDetailType;
|
detail: GroupV2ChangeDetailType;
|
||||||
isLastText: boolean;
|
isLastText: boolean;
|
||||||
groupMemberships?: ReadonlyArray<{
|
groupMemberships?: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>;
|
}>;
|
||||||
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
groupBannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||||
|
@ -206,10 +206,10 @@ function GroupV2Detail({
|
||||||
if (
|
if (
|
||||||
!isLastText ||
|
!isLastText ||
|
||||||
detail.type !== 'admin-approval-bounce' ||
|
detail.type !== 'admin-approval-bounce' ||
|
||||||
!detail.uuid
|
!detail.aci
|
||||||
) {
|
) {
|
||||||
log.warn(
|
log.warn(
|
||||||
'GroupV2Detail: ConfirmingblockGroupLinkRequests but missing uuid or wrong change type'
|
'GroupV2Detail: ConfirmingblockGroupLinkRequests but missing aci or wrong change type'
|
||||||
);
|
);
|
||||||
modalNode = undefined;
|
modalNode = undefined;
|
||||||
break;
|
break;
|
||||||
|
@ -221,7 +221,7 @@ function GroupV2Detail({
|
||||||
title={i18n('icu:PendingRequests--block--title')}
|
title={i18n('icu:PendingRequests--block--title')}
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
action: () => blockGroupLinkRequests(conversationId, detail.uuid),
|
action: () => blockGroupLinkRequests(conversationId, detail.aci),
|
||||||
text: i18n('icu:PendingRequests--block--confirm'),
|
text: i18n('icu:PendingRequests--block--confirm'),
|
||||||
style: 'affirmative',
|
style: 'affirmative',
|
||||||
},
|
},
|
||||||
|
@ -233,7 +233,7 @@ function GroupV2Detail({
|
||||||
id="icu:PendingRequests--block--contents"
|
id="icu:PendingRequests--block--contents"
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
components={{
|
components={{
|
||||||
name: renderContact(detail.uuid),
|
name: renderContact(detail.aci),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ConfirmationDialog>
|
</ConfirmationDialog>
|
||||||
|
@ -261,11 +261,11 @@ function GroupV2Detail({
|
||||||
isLastText &&
|
isLastText &&
|
||||||
detail.type === 'admin-approval-bounce' &&
|
detail.type === 'admin-approval-bounce' &&
|
||||||
areWeAdmin &&
|
areWeAdmin &&
|
||||||
detail.uuid &&
|
detail.aci &&
|
||||||
detail.uuid !== ourAci &&
|
detail.aci !== ourAci &&
|
||||||
(!fromId || fromId === detail.uuid) &&
|
(!fromId || fromId === detail.aci) &&
|
||||||
!groupMemberships?.some(item => item.uuid === detail.uuid) &&
|
!groupMemberships?.some(item => item.aci === detail.aci) &&
|
||||||
!groupBannedMemberships?.some(uuid => uuid === detail.uuid)
|
!groupBannedMemberships?.some(serviceId => serviceId === detail.aci)
|
||||||
) {
|
) {
|
||||||
buttonNode = (
|
buttonNode = (
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -319,7 +319,7 @@ export type PropsActions = {
|
||||||
messageExpanded: (id: string, displayLimit: number) => unknown;
|
messageExpanded: (id: string, displayLimit: number) => unknown;
|
||||||
checkForAccount: (phoneNumber: string) => unknown;
|
checkForAccount: (phoneNumber: string) => unknown;
|
||||||
|
|
||||||
startConversation: (e164: string, uuid: ServiceIdString) => void;
|
startConversation: (e164: string, serviceId: ServiceIdString) => void;
|
||||||
showConversation: ShowConversationType;
|
showConversation: ShowConversationType;
|
||||||
openGiftBadge: (messageId: string) => void;
|
openGiftBadge: (messageId: string) => void;
|
||||||
pushPanelForConversation: PushPanelForConversationActionType;
|
pushPanelForConversation: PushPanelForConversationActionType;
|
||||||
|
@ -516,7 +516,7 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const { contact, checkForAccount } = this.props;
|
const { contact, checkForAccount } = this.props;
|
||||||
if (contact && contact.firstNumber && !contact.uuid) {
|
if (contact && contact.firstNumber && !contact.serviceId) {
|
||||||
checkForAccount(contact.firstNumber);
|
checkForAccount(contact.firstNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1637,7 +1637,7 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
this.getMetadataPlacement() !== MetadataPlacement.NotRendered;
|
this.getMetadataPlacement() !== MetadataPlacement.NotRendered;
|
||||||
|
|
||||||
const otherContent =
|
const otherContent =
|
||||||
(contact && contact.firstNumber && contact.uuid) || withCaption;
|
(contact && contact.firstNumber && contact.serviceId) || withCaption;
|
||||||
const tabIndex = otherContent ? 0 : -1;
|
const tabIndex = otherContent ? 0 : -1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1647,10 +1647,10 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const signalAccount =
|
const signalAccount =
|
||||||
contact.firstNumber && contact.uuid
|
contact.firstNumber && contact.serviceId
|
||||||
? {
|
? {
|
||||||
phoneNumber: contact.firstNumber,
|
phoneNumber: contact.firstNumber,
|
||||||
uuid: contact.uuid,
|
serviceId: contact.serviceId,
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
@ -1678,8 +1678,8 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
if (!contact) {
|
if (!contact) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { firstNumber, uuid } = contact;
|
const { firstNumber, serviceId } = contact;
|
||||||
if (!firstNumber || !uuid) {
|
if (!firstNumber || !serviceId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1689,7 +1689,7 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
startConversation(firstNumber, uuid);
|
startConversation(firstNumber, serviceId);
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'module-message__send-message-button',
|
'module-message__send-message-button',
|
||||||
|
@ -2456,8 +2456,8 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contact && contact.firstNumber && contact.uuid) {
|
if (contact && contact.firstNumber && contact.serviceId) {
|
||||||
startConversation(contact.firstNumber, contact.uuid);
|
startConversation(contact.firstNumber, contact.serviceId);
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -2466,10 +2466,10 @@ export class Message extends React.PureComponent<Props, State> {
|
||||||
|
|
||||||
if (contact) {
|
if (contact) {
|
||||||
const signalAccount =
|
const signalAccount =
|
||||||
contact.firstNumber && contact.uuid
|
contact.firstNumber && contact.serviceId
|
||||||
? {
|
? {
|
||||||
phoneNumber: contact.firstNumber,
|
phoneNumber: contact.firstNumber,
|
||||||
uuid: contact.uuid,
|
serviceId: contact.serviceId,
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
pushPanelForConversation({
|
pushPanelForConversation({
|
||||||
|
|
|
@ -128,7 +128,7 @@ export function Mention(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 5,
|
start: 5,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_1,
|
mentionAci: SERVICE_ID_1,
|
||||||
replacementText: 'Bender B Rodriguez 🤖',
|
replacementText: 'Bender B Rodriguez 🤖',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -150,21 +150,21 @@ export function MultipleMentions(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 2,
|
start: 2,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_2,
|
mentionAci: SERVICE_ID_2,
|
||||||
replacementText: 'Philip J Fry',
|
replacementText: 'Philip J Fry',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 4,
|
start: 4,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Professor Farnsworth',
|
replacementText: 'Professor Farnsworth',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 0,
|
start: 0,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_4,
|
mentionAci: SERVICE_ID_4,
|
||||||
replacementText: 'Yancy Fry',
|
replacementText: 'Yancy Fry',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -192,21 +192,21 @@ export function ComplexMessageBody(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 78,
|
start: 78,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_5,
|
mentionAci: SERVICE_ID_5,
|
||||||
replacementText: 'Acid Burn',
|
replacementText: 'Acid Burn',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 80,
|
start: 80,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_6,
|
mentionAci: SERVICE_ID_6,
|
||||||
replacementText: 'Cereal Killer',
|
replacementText: 'Cereal Killer',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 4,
|
start: 4,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_6,
|
mentionAci: SERVICE_ID_6,
|
||||||
replacementText: 'Zero Cool',
|
replacementText: 'Zero Cool',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -324,14 +324,14 @@ export function FormattingSpoiler(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 54,
|
start: 54,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_7,
|
mentionAci: SERVICE_ID_7,
|
||||||
conversationID: 'a',
|
conversationID: 'a',
|
||||||
replacementText: '🅰️ Alice',
|
replacementText: '🅰️ Alice',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 60,
|
start: 60,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_8,
|
mentionAci: SERVICE_ID_8,
|
||||||
conversationID: 'b',
|
conversationID: 'b',
|
||||||
replacementText: '🅱️ Bob',
|
replacementText: '🅱️ Bob',
|
||||||
},
|
},
|
||||||
|
@ -384,35 +384,35 @@ export function FormattingNesting(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 29,
|
start: 29,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_7,
|
mentionAci: SERVICE_ID_7,
|
||||||
conversationID: 'a',
|
conversationID: 'a',
|
||||||
replacementText: '🅰️ Alice',
|
replacementText: '🅰️ Alice',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 61,
|
start: 61,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_8,
|
mentionAci: SERVICE_ID_8,
|
||||||
conversationID: 'b',
|
conversationID: 'b',
|
||||||
replacementText: '🅱️ Bob',
|
replacementText: '🅱️ Bob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 68,
|
start: 68,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_9,
|
mentionAci: SERVICE_ID_9,
|
||||||
conversationID: 'c',
|
conversationID: 'c',
|
||||||
replacementText: 'Charlie',
|
replacementText: 'Charlie',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 80,
|
start: 80,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_10,
|
mentionAci: SERVICE_ID_10,
|
||||||
conversationID: 'd',
|
conversationID: 'd',
|
||||||
replacementText: 'Dan',
|
replacementText: 'Dan',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
start: 105,
|
start: 105,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_11,
|
mentionAci: SERVICE_ID_11,
|
||||||
conversationID: 'e',
|
conversationID: 'e',
|
||||||
replacementText: 'Eve',
|
replacementText: 'Eve',
|
||||||
},
|
},
|
||||||
|
@ -452,7 +452,7 @@ export function FormattingComplex(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 24,
|
start: 24,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
replacementText: '🤖 Hello',
|
replacementText: '🤖 Hello',
|
||||||
},
|
},
|
||||||
|
@ -484,7 +484,7 @@ export function FormattingComplex(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 491,
|
start: 491,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
replacementText: '🤖 Hello',
|
replacementText: '🤖 Hello',
|
||||||
},
|
},
|
||||||
|
|
|
@ -92,7 +92,7 @@ export function LongTextWithMention(): JSX.Element {
|
||||||
{
|
{
|
||||||
start: 800,
|
start: 800,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: generateAci(),
|
mentionAci: generateAci(),
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
replacementText: 'Alice',
|
replacementText: 'Alice',
|
||||||
},
|
},
|
||||||
|
|
|
@ -267,8 +267,8 @@ const actions = () => ({
|
||||||
),
|
),
|
||||||
blockGroupLinkRequests: action('blockGroupLinkRequests'),
|
blockGroupLinkRequests: action('blockGroupLinkRequests'),
|
||||||
checkForAccount: action('checkForAccount'),
|
checkForAccount: action('checkForAccount'),
|
||||||
clearInvitedUuidsForNewlyCreatedGroup: action(
|
clearInvitedServiceIdsForNewlyCreatedGroup: action(
|
||||||
'clearInvitedUuidsForNewlyCreatedGroup'
|
'clearInvitedServiceIdsForNewlyCreatedGroup'
|
||||||
),
|
),
|
||||||
setIsNearBottom: action('setIsNearBottom'),
|
setIsNearBottom: action('setIsNearBottom'),
|
||||||
loadOlderMessages: action('loadOlderMessages'),
|
loadOlderMessages: action('loadOlderMessages'),
|
||||||
|
|
|
@ -148,7 +148,7 @@ export type PropsActionsType = {
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
) => void;
|
) => void;
|
||||||
clearInvitedUuidsForNewlyCreatedGroup: () => void;
|
clearInvitedServiceIdsForNewlyCreatedGroup: () => void;
|
||||||
clearTargetedMessage: () => unknown;
|
clearTargetedMessage: () => unknown;
|
||||||
closeContactSpoofingReview: () => void;
|
closeContactSpoofingReview: () => void;
|
||||||
loadOlderMessages: (conversationId: string, messageId: string) => unknown;
|
loadOlderMessages: (conversationId: string, messageId: string) => unknown;
|
||||||
|
@ -743,7 +743,7 @@ export class Timeline extends React.Component<
|
||||||
public override render(): JSX.Element | null {
|
public override render(): JSX.Element | null {
|
||||||
const {
|
const {
|
||||||
acknowledgeGroupMemberNameCollisions,
|
acknowledgeGroupMemberNameCollisions,
|
||||||
clearInvitedUuidsForNewlyCreatedGroup,
|
clearInvitedServiceIdsForNewlyCreatedGroup,
|
||||||
closeContactSpoofingReview,
|
closeContactSpoofingReview,
|
||||||
contactSpoofingReview,
|
contactSpoofingReview,
|
||||||
getPreferredBadge,
|
getPreferredBadge,
|
||||||
|
@ -1139,7 +1139,7 @@ export class Timeline extends React.Component<
|
||||||
contacts={invitedContactsForNewlyCreatedGroup}
|
contacts={invitedContactsForNewlyCreatedGroup}
|
||||||
getPreferredBadge={getPreferredBadge}
|
getPreferredBadge={getPreferredBadge}
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
onClose={clearInvitedUuidsForNewlyCreatedGroup}
|
onClose={clearInvitedServiceIdsForNewlyCreatedGroup}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1676,7 +1676,7 @@ Mentions.args = {
|
||||||
{
|
{
|
||||||
start: 0,
|
start: 0,
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: generateAci(),
|
mentionAci: generateAci(),
|
||||||
replacementText: 'Zapp Brannigan',
|
replacementText: 'Zapp Brannigan',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
},
|
},
|
||||||
|
@ -1944,7 +1944,7 @@ EmbeddedContactWithSendMessage.args = {
|
||||||
contact: {
|
contact: {
|
||||||
...fullContact,
|
...fullContact,
|
||||||
firstNumber: fullContact.number[0].value,
|
firstNumber: fullContact.number[0].value,
|
||||||
uuid: generateAci(),
|
serviceId: generateAci(),
|
||||||
},
|
},
|
||||||
direction: 'incoming',
|
direction: 'incoming',
|
||||||
};
|
};
|
||||||
|
|
|
@ -234,7 +234,7 @@ export function WithCallHistoryGroup(): JSX.Element {
|
||||||
<ConversationDetails
|
<ConversationDetails
|
||||||
{...props}
|
{...props}
|
||||||
callHistoryGroup={{
|
callHistoryGroup={{
|
||||||
peerId: props.conversation?.uuid ?? '',
|
peerId: props.conversation?.serviceId ?? '',
|
||||||
mode: CallMode.Direct,
|
mode: CallMode.Direct,
|
||||||
type: CallType.Video,
|
type: CallType.Video,
|
||||||
direction: CallDirection.Incoming,
|
direction: CallDirection.Incoming,
|
||||||
|
|
|
@ -292,7 +292,8 @@ function getConfirmationMessage({
|
||||||
}
|
}
|
||||||
|
|
||||||
const inviter = members.find(
|
const inviter = members.find(
|
||||||
({ uuid }) => uuid === firstPendingMembership.metadata.addedByUserId
|
({ serviceId }) =>
|
||||||
|
serviceId === firstPendingMembership.metadata.addedByUserId
|
||||||
);
|
);
|
||||||
|
|
||||||
if (inviter === undefined) {
|
if (inviter === undefined) {
|
||||||
|
@ -412,13 +413,16 @@ function MembersPendingProfileKey({
|
||||||
groupedPendingMemberships;
|
groupedPendingMemberships;
|
||||||
|
|
||||||
const otherPendingMemberships = Object.keys(otherPendingMembershipGroups)
|
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)
|
.filter((member): member is ConversationType => member !== undefined)
|
||||||
.map(member => {
|
.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 {
|
return {
|
||||||
member,
|
member,
|
||||||
pendingMemberships: otherPendingMembershipGroups[member.uuid],
|
pendingMemberships: otherPendingMembershipGroups[member.serviceId],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ type PropsType = {
|
||||||
| 'sharedGroupNames'
|
| 'sharedGroupNames'
|
||||||
| 'title'
|
| 'title'
|
||||||
| 'unblurredAvatarPath'
|
| 'unblurredAvatarPath'
|
||||||
| 'uuid'
|
| 'serviceId'
|
||||||
> &
|
> &
|
||||||
(
|
(
|
||||||
| { badge?: undefined; theme?: ThemeType }
|
| { badge?: undefined; theme?: ThemeType }
|
||||||
|
@ -109,12 +109,12 @@ export const BaseConversationListItem: FunctionComponent<PropsType> =
|
||||||
unblurredAvatarPath,
|
unblurredAvatarPath,
|
||||||
unreadCount,
|
unreadCount,
|
||||||
unreadMentionsCount,
|
unreadMentionsCount,
|
||||||
uuid,
|
serviceId,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const identifier = id ? cleanId(id) : undefined;
|
const identifier = id ? cleanId(id) : undefined;
|
||||||
const htmlId = useMemo(() => generateUuid(), []);
|
const htmlId = useMemo(() => generateUuid(), []);
|
||||||
const testId = overrideTestId || groupId || uuid;
|
const testId = overrideTestId || groupId || serviceId;
|
||||||
const isUnread = isConversationUnread({ markedUnread, unreadCount });
|
const isUnread = isConversationUnread({ markedUnread, unreadCount });
|
||||||
|
|
||||||
const isAvatarNoteToSelf = isBoolean(isNoteToSelf)
|
const isAvatarNoteToSelf = isBoolean(isNoteToSelf)
|
||||||
|
|
|
@ -38,7 +38,7 @@ export type PropsDataType = {
|
||||||
| 'title'
|
| 'title'
|
||||||
| 'type'
|
| 'type'
|
||||||
| 'unblurredAvatarPath'
|
| 'unblurredAvatarPath'
|
||||||
| 'uuid'
|
| 'serviceId'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type PropsHousekeepingType = {
|
type PropsHousekeepingType = {
|
||||||
|
|
|
@ -39,7 +39,7 @@ export type ContactListItemConversationType = Pick<
|
||||||
| 'unblurredAvatarPath'
|
| 'unblurredAvatarPath'
|
||||||
| 'username'
|
| 'username'
|
||||||
| 'e164'
|
| 'e164'
|
||||||
| 'uuid'
|
| 'serviceId'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type PropsDataType = ContactListItemConversationType & {
|
type PropsDataType = ContactListItemConversationType & {
|
||||||
|
@ -85,7 +85,7 @@ export const ContactListItem: FunctionComponent<PropsType> = React.memo(
|
||||||
title,
|
title,
|
||||||
type,
|
type,
|
||||||
unblurredAvatarPath,
|
unblurredAvatarPath,
|
||||||
uuid,
|
serviceId,
|
||||||
}) {
|
}) {
|
||||||
const [isConfirmingBlocking, setConfirmingBlocking] = useState(false);
|
const [isConfirmingBlocking, setConfirmingBlocking] = useState(false);
|
||||||
const [isConfirmingRemoving, setConfirmingRemoving] = useState(false);
|
const [isConfirmingRemoving, setConfirmingRemoving] = useState(false);
|
||||||
|
@ -149,7 +149,7 @@ export const ContactListItem: FunctionComponent<PropsType> = React.memo(
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<ContactName
|
<ContactName
|
||||||
isSignalConversation={isSignalConversation({ id, uuid })}
|
isSignalConversation={isSignalConversation({ id, serviceId })}
|
||||||
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
||||||
title={title}
|
title={title}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -64,7 +64,7 @@ export type PropsData = Pick<
|
||||||
| 'unblurredAvatarPath'
|
| 'unblurredAvatarPath'
|
||||||
| 'unreadCount'
|
| 'unreadCount'
|
||||||
| 'unreadMentionsCount'
|
| 'unreadMentionsCount'
|
||||||
| 'uuid'
|
| 'serviceId'
|
||||||
> & {
|
> & {
|
||||||
badge?: BadgeType;
|
badge?: BadgeType;
|
||||||
};
|
};
|
||||||
|
@ -108,7 +108,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
||||||
unblurredAvatarPath,
|
unblurredAvatarPath,
|
||||||
unreadCount,
|
unreadCount,
|
||||||
unreadMentionsCount,
|
unreadMentionsCount,
|
||||||
uuid,
|
serviceId,
|
||||||
}) {
|
}) {
|
||||||
const isMuted = Boolean(muteExpiresAt && Date.now() < muteExpiresAt);
|
const isMuted = Boolean(muteExpiresAt && Date.now() < muteExpiresAt);
|
||||||
const headerName = (
|
const headerName = (
|
||||||
|
@ -122,7 +122,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
||||||
) : (
|
) : (
|
||||||
<ContactName
|
<ContactName
|
||||||
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
module={HEADER_CONTACT_NAME_CLASS_NAME}
|
||||||
isSignalConversation={isSignalConversation({ id, uuid })}
|
isSignalConversation={isSignalConversation({ id, serviceId })}
|
||||||
title={title}
|
title={title}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -221,7 +221,7 @@ export const ConversationListItem: FunctionComponent<Props> = React.memo(
|
||||||
unreadCount={unreadCount}
|
unreadCount={unreadCount}
|
||||||
unreadMentionsCount={unreadMentionsCount}
|
unreadMentionsCount={unreadMentionsCount}
|
||||||
unblurredAvatarPath={unblurredAvatarPath}
|
unblurredAvatarPath={unblurredAvatarPath}
|
||||||
uuid={uuid}
|
serviceId={serviceId}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export type GroupListItemConversationType = Pick<
|
||||||
disabledReason: DisabledReason | undefined;
|
disabledReason: DisabledReason | undefined;
|
||||||
membersCount: number;
|
membersCount: number;
|
||||||
memberships: ReadonlyArray<{
|
memberships: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>;
|
}>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,14 +203,14 @@ export function Mention(): JSX.Element {
|
||||||
bodyRanges: [
|
bodyRanges: [
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Shoe',
|
replacementText: 'Shoe',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 113,
|
start: 113,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Shoe',
|
replacementText: 'Shoe',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 237,
|
start: 237,
|
||||||
|
@ -235,7 +235,7 @@ export function MentionRegexp(): JSX.Element {
|
||||||
bodyRanges: [
|
bodyRanges: [
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'RegExp',
|
replacementText: 'RegExp',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 0,
|
start: 0,
|
||||||
|
@ -260,7 +260,7 @@ export function MentionNoMatches(): JSX.Element {
|
||||||
bodyRanges: [
|
bodyRanges: [
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Neo',
|
replacementText: 'Neo',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 0,
|
start: 0,
|
||||||
|
@ -284,14 +284,14 @@ export const _MentionNoMatches = (): JSX.Element => {
|
||||||
bodyRanges: [
|
bodyRanges: [
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Shoe',
|
replacementText: 'Shoe',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 113,
|
start: 113,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_3,
|
mentionAci: SERVICE_ID_3,
|
||||||
replacementText: 'Shoe',
|
replacementText: 'Shoe',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 237,
|
start: 237,
|
||||||
|
@ -316,14 +316,14 @@ export function DoubleMention(): JSX.Element {
|
||||||
bodyRanges: [
|
bodyRanges: [
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_2,
|
mentionAci: SERVICE_ID_2,
|
||||||
replacementText: 'Alice',
|
replacementText: 'Alice',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 4,
|
start: 4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
length: 1,
|
length: 1,
|
||||||
mentionUuid: SERVICE_ID_1,
|
mentionAci: SERVICE_ID_1,
|
||||||
replacementText: 'Bob',
|
replacementText: 'Bob',
|
||||||
conversationID: 'x',
|
conversationID: 'x',
|
||||||
start: 6,
|
start: 6,
|
||||||
|
|
|
@ -86,13 +86,15 @@ export function renderChangeDetail<T>(
|
||||||
return renderString(id, localizer, components);
|
return renderString(id, localizer, components);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isOurUuid = (uuid?: ServiceIdString): boolean => {
|
const isOurServiceId = (serviceId?: ServiceIdString): boolean => {
|
||||||
if (!uuid) {
|
if (!serviceId) {
|
||||||
return false;
|
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 (detail.type === 'create') {
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
|
@ -249,8 +251,8 @@ export function renderChangeDetail<T>(
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-add') {
|
if (detail.type === 'member-add') {
|
||||||
const { uuid } = detail;
|
const { aci } = detail;
|
||||||
const weAreJoiner = isOurUuid(uuid);
|
const weAreJoiner = isOurServiceId(aci);
|
||||||
|
|
||||||
if (weAreJoiner) {
|
if (weAreJoiner) {
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
|
@ -265,25 +267,25 @@ export function renderChangeDetail<T>(
|
||||||
}
|
}
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--member-add--other--you', {
|
return i18n('icu:GroupV2--member-add--other--you', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
return i18n('icu:GroupV2--member-add--other--other', {
|
return i18n('icu:GroupV2--member-add--other--other', {
|
||||||
adderName: renderContact(from),
|
adderName: renderContact(from),
|
||||||
addeeName: renderContact(uuid),
|
addeeName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return i18n('icu:GroupV2--member-add--other--unknown', {
|
return i18n('icu:GroupV2--member-add--other--unknown', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-add-from-invite') {
|
if (detail.type === 'member-add-from-invite') {
|
||||||
const { uuid, inviter } = detail;
|
const { aci, inviter } = detail;
|
||||||
const weAreJoiner = isOurUuid(uuid);
|
const weAreJoiner = isOurServiceId(aci);
|
||||||
const weAreInviter = isOurUuid(inviter);
|
const weAreInviter = isOurServiceId(inviter);
|
||||||
|
|
||||||
if (!from || from !== uuid) {
|
if (!from || from !== aci) {
|
||||||
if (weAreJoiner) {
|
if (weAreJoiner) {
|
||||||
// They can't be the same, no fromYou check here
|
// They can't be the same, no fromYou check here
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -296,17 +298,17 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--member-add--invited--you', {
|
return i18n('icu:GroupV2--member-add--invited--you', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
return i18n('icu:GroupV2--member-add--invited--other', {
|
return i18n('icu:GroupV2--member-add--invited--other', {
|
||||||
memberName: renderContact(from),
|
memberName: renderContact(from),
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return i18n('icu:GroupV2--member-add--invited--unknown', {
|
return i18n('icu:GroupV2--member-add--invited--unknown', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,12 +322,12 @@ export function renderChangeDetail<T>(
|
||||||
}
|
}
|
||||||
if (weAreInviter) {
|
if (weAreInviter) {
|
||||||
return i18n('icu:GroupV2--member-add--from-invite--from-you', {
|
return i18n('icu:GroupV2--member-add--from-invite--from-you', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (inviter) {
|
if (inviter) {
|
||||||
return i18n('icu:GroupV2--member-add--from-invite--other', {
|
return i18n('icu:GroupV2--member-add--from-invite--other', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
inviterName: renderContact(inviter),
|
inviterName: renderContact(inviter),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -333,17 +335,17 @@ export function renderChangeDetail<T>(
|
||||||
'icu:GroupV2--member-add--from-invite--other-no-from',
|
'icu:GroupV2--member-add--from-invite--other-no-from',
|
||||||
|
|
||||||
{
|
{
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(aci),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-add-from-link') {
|
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');
|
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', {
|
return i18n('icu:GroupV2--member-add-from-link--other', {
|
||||||
memberName: renderContact(from),
|
memberName: renderContact(from),
|
||||||
});
|
});
|
||||||
|
@ -353,12 +355,12 @@ export function renderChangeDetail<T>(
|
||||||
// from group change events, which always have a sender.
|
// from group change events, which always have a sender.
|
||||||
log.warn('member-add-from-link change type; we have no from!');
|
log.warn('member-add-from-link change type; we have no from!');
|
||||||
return i18n('icu:GroupV2--member-add--other--unknown', {
|
return i18n('icu:GroupV2--member-add--other--unknown', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-add-from-admin-approval') {
|
if (detail.type === 'member-add-from-admin-approval') {
|
||||||
const { uuid } = detail;
|
const { aci } = detail;
|
||||||
const weAreJoiner = isOurUuid(uuid);
|
const weAreJoiner = isOurServiceId(aci);
|
||||||
|
|
||||||
if (weAreJoiner) {
|
if (weAreJoiner) {
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -381,7 +383,7 @@ export function renderChangeDetail<T>(
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--member-add-from-admin-approval--other--you',
|
'icu:GroupV2--member-add-from-admin-approval--other--you',
|
||||||
|
|
||||||
{ joinerName: renderContact(uuid) }
|
{ joinerName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -390,7 +392,7 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
{
|
{
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
joinerName: renderContact(uuid),
|
joinerName: renderContact(aci),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -401,12 +403,12 @@ export function renderChangeDetail<T>(
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--member-add-from-admin-approval--other--unknown',
|
'icu:GroupV2--member-add-from-admin-approval--other--unknown',
|
||||||
|
|
||||||
{ joinerName: renderContact(uuid) }
|
{ joinerName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-remove') {
|
if (detail.type === 'member-remove') {
|
||||||
const { uuid } = detail;
|
const { aci } = detail;
|
||||||
const weAreLeaver = isOurUuid(uuid);
|
const weAreLeaver = isOurServiceId(aci);
|
||||||
|
|
||||||
if (weAreLeaver) {
|
if (weAreLeaver) {
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
|
@ -422,10 +424,10 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--member-remove--other--you', {
|
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', {
|
return i18n('icu:GroupV2--member-remove--other--self', {
|
||||||
memberName: renderContact(from),
|
memberName: renderContact(from),
|
||||||
});
|
});
|
||||||
|
@ -433,16 +435,16 @@ export function renderChangeDetail<T>(
|
||||||
if (from) {
|
if (from) {
|
||||||
return i18n('icu:GroupV2--member-remove--other--other', {
|
return i18n('icu:GroupV2--member-remove--other--other', {
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return i18n('icu:GroupV2--member-remove--other--unknown', {
|
return i18n('icu:GroupV2--member-remove--other--unknown', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (detail.type === 'member-privilege') {
|
if (detail.type === 'member-privilege') {
|
||||||
const { uuid, newPrivilege } = detail;
|
const { aci, newPrivilege } = detail;
|
||||||
const weAreMember = isOurUuid(uuid);
|
const weAreMember = isOurServiceId(aci);
|
||||||
|
|
||||||
if (newPrivilege === RoleEnum.ADMINISTRATOR) {
|
if (newPrivilege === RoleEnum.ADMINISTRATOR) {
|
||||||
if (weAreMember) {
|
if (weAreMember) {
|
||||||
|
@ -459,17 +461,17 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--member-privilege--promote--other--you', {
|
return i18n('icu:GroupV2--member-privilege--promote--other--you', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
return i18n('icu:GroupV2--member-privilege--promote--other--other', {
|
return i18n('icu:GroupV2--member-privilege--promote--other--other', {
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return i18n('icu:GroupV2--member-privilege--promote--other--unknown', {
|
return i18n('icu:GroupV2--member-privilege--promote--other--unknown', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (newPrivilege === RoleEnum.DEFAULT) {
|
if (newPrivilege === RoleEnum.DEFAULT) {
|
||||||
|
@ -484,7 +486,7 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--member-privilege--demote--other--you', {
|
return i18n('icu:GroupV2--member-privilege--demote--other--you', {
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -493,14 +495,14 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
{
|
{
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
memberName: renderContact(uuid),
|
memberName: renderContact(aci),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--member-privilege--demote--other--unknown',
|
'icu:GroupV2--member-privilege--demote--other--unknown',
|
||||||
|
|
||||||
{ memberName: renderContact(uuid) }
|
{ memberName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
log.warn(
|
log.warn(
|
||||||
|
@ -509,8 +511,8 @@ export function renderChangeDetail<T>(
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (detail.type === 'pending-add-one') {
|
if (detail.type === 'pending-add-one') {
|
||||||
const { uuid } = detail;
|
const { serviceId } = detail;
|
||||||
const weAreInvited = isOurUuid(uuid);
|
const weAreInvited = isOurServiceId(serviceId);
|
||||||
if (weAreInvited) {
|
if (weAreInvited) {
|
||||||
if (from) {
|
if (from) {
|
||||||
return i18n('icu:GroupV2--pending-add--one--you--other', {
|
return i18n('icu:GroupV2--pending-add--one--you--other', {
|
||||||
|
@ -521,7 +523,7 @@ export function renderChangeDetail<T>(
|
||||||
}
|
}
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n('icu:GroupV2--pending-add--one--other--you', {
|
return i18n('icu:GroupV2--pending-add--one--other--you', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(serviceId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -550,23 +552,23 @@ export function renderChangeDetail<T>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (detail.type === 'pending-remove-one') {
|
if (detail.type === 'pending-remove-one') {
|
||||||
const { inviter, uuid } = detail;
|
const { inviter, serviceId } = detail;
|
||||||
const weAreInviter = isOurUuid(inviter);
|
const weAreInviter = isOurServiceId(inviter);
|
||||||
const weAreInvited = isOurUuid(uuid);
|
const weAreInvited = isOurServiceId(serviceId);
|
||||||
const sentByInvited = Boolean(from && from === uuid);
|
const sentByInvited = Boolean(from && from === serviceId);
|
||||||
const sentByInviter = Boolean(from && inviter && from === inviter);
|
const sentByInviter = Boolean(from && inviter && from === inviter);
|
||||||
|
|
||||||
if (weAreInviter) {
|
if (weAreInviter) {
|
||||||
if (sentByInvited) {
|
if (sentByInvited) {
|
||||||
return i18n('icu:GroupV2--pending-remove--decline--you', {
|
return i18n('icu:GroupV2--pending-remove--decline--you', {
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(serviceId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--you',
|
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--you',
|
||||||
|
|
||||||
{ inviteeName: renderContact(uuid) }
|
{ inviteeName: renderContact(serviceId) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -575,14 +577,14 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
{
|
{
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
inviteeName: renderContact(uuid),
|
inviteeName: renderContact(serviceId),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--unknown',
|
'icu:GroupV2--pending-remove--revoke-invite-from-you--one--unknown',
|
||||||
|
|
||||||
{ inviteeName: renderContact(uuid) }
|
{ inviteeName: renderContact(serviceId) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (sentByInvited) {
|
if (sentByInvited) {
|
||||||
|
@ -646,7 +648,7 @@ export function renderChangeDetail<T>(
|
||||||
}
|
}
|
||||||
if (detail.type === 'pending-remove-many') {
|
if (detail.type === 'pending-remove-many') {
|
||||||
const { count, inviter } = detail;
|
const { count, inviter } = detail;
|
||||||
const weAreInviter = isOurUuid(inviter);
|
const weAreInviter = isOurServiceId(inviter);
|
||||||
|
|
||||||
if (weAreInviter) {
|
if (weAreInviter) {
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
|
@ -725,19 +727,19 @@ export function renderChangeDetail<T>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (detail.type === 'admin-approval-add-one') {
|
if (detail.type === 'admin-approval-add-one') {
|
||||||
const { uuid } = detail;
|
const { aci } = detail;
|
||||||
const weAreJoiner = isOurUuid(uuid);
|
const weAreJoiner = isOurServiceId(aci);
|
||||||
|
|
||||||
if (weAreJoiner) {
|
if (weAreJoiner) {
|
||||||
return i18n('icu:GroupV2--admin-approval-add-one--you');
|
return i18n('icu:GroupV2--admin-approval-add-one--you');
|
||||||
}
|
}
|
||||||
return i18n('icu:GroupV2--admin-approval-add-one--other', {
|
return i18n('icu:GroupV2--admin-approval-add-one--other', {
|
||||||
joinerName: renderContact(uuid),
|
joinerName: renderContact(aci),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (detail.type === 'admin-approval-remove-one') {
|
if (detail.type === 'admin-approval-remove-one') {
|
||||||
const { uuid } = detail;
|
const { aci } = detail;
|
||||||
const weAreJoiner = isOurUuid(uuid);
|
const weAreJoiner = isOurServiceId(aci);
|
||||||
|
|
||||||
if (weAreJoiner) {
|
if (weAreJoiner) {
|
||||||
if (fromYou) {
|
if (fromYou) {
|
||||||
|
@ -750,14 +752,14 @@ export function renderChangeDetail<T>(
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--admin-approval-remove-one--other--you',
|
'icu:GroupV2--admin-approval-remove-one--other--you',
|
||||||
|
|
||||||
{ joinerName: renderContact(uuid) }
|
{ joinerName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (from && from === uuid) {
|
if (from && from === aci) {
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--admin-approval-remove-one--other--own',
|
'icu:GroupV2--admin-approval-remove-one--other--own',
|
||||||
|
|
||||||
{ joinerName: renderContact(uuid) }
|
{ joinerName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (from) {
|
if (from) {
|
||||||
|
@ -766,7 +768,7 @@ export function renderChangeDetail<T>(
|
||||||
|
|
||||||
{
|
{
|
||||||
adminName: renderContact(from),
|
adminName: renderContact(from),
|
||||||
joinerName: renderContact(uuid),
|
joinerName: renderContact(aci),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -776,20 +778,20 @@ export function renderChangeDetail<T>(
|
||||||
return i18n(
|
return i18n(
|
||||||
'icu:GroupV2--admin-approval-remove-one--other--own',
|
'icu:GroupV2--admin-approval-remove-one--other--own',
|
||||||
|
|
||||||
{ joinerName: renderContact(uuid) }
|
{ joinerName: renderContact(aci) }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (detail.type === 'admin-approval-bounce') {
|
if (detail.type === 'admin-approval-bounce') {
|
||||||
const { uuid, times, isApprovalPending } = detail;
|
const { aci, times, isApprovalPending } = detail;
|
||||||
|
|
||||||
let firstMessage: T | string;
|
let firstMessage: T | string;
|
||||||
if (times === 1) {
|
if (times === 1) {
|
||||||
firstMessage = i18n('icu:GroupV2--admin-approval-bounce--one', {
|
firstMessage = i18n('icu:GroupV2--admin-approval-bounce--one', {
|
||||||
joinerName: renderContact(uuid),
|
joinerName: renderContact(aci),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
firstMessage = i18n('icu:GroupV2--admin-approval-bounce', {
|
firstMessage = i18n('icu:GroupV2--admin-approval-bounce', {
|
||||||
joinerName: renderContact(uuid),
|
joinerName: renderContact(aci),
|
||||||
numberOfRequests: times,
|
numberOfRequests: times,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -801,7 +803,7 @@ export function renderChangeDetail<T>(
|
||||||
const secondMessage = renderChangeDetail(
|
const secondMessage = renderChangeDetail(
|
||||||
{
|
{
|
||||||
type: 'admin-approval-add-one',
|
type: 'admin-approval-add-one',
|
||||||
uuid,
|
aci,
|
||||||
},
|
},
|
||||||
options
|
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
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import type { AciString } from '../types/ServiceId';
|
||||||
import { usePrevious } from './usePrevious';
|
import { usePrevious } from './usePrevious';
|
||||||
|
|
||||||
type RemoteParticipant = {
|
type RemoteParticipant = {
|
||||||
hasRemoteVideo: boolean;
|
hasRemoteVideo: boolean;
|
||||||
presenting: boolean;
|
presenting: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
uuid?: string;
|
aci?: AciString;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useActivateSpeakerViewOnPresenting({
|
export function useActivateSpeakerViewOnPresenting({
|
||||||
|
@ -20,20 +21,20 @@ export function useActivateSpeakerViewOnPresenting({
|
||||||
switchToPresentationView: () => void;
|
switchToPresentationView: () => void;
|
||||||
switchFromPresentationView: () => void;
|
switchFromPresentationView: () => void;
|
||||||
}): void {
|
}): void {
|
||||||
const presenterUuid = remoteParticipants.find(
|
const presenterAci = remoteParticipants.find(
|
||||||
participant => participant.presenting
|
participant => participant.presenting
|
||||||
)?.uuid;
|
)?.aci;
|
||||||
const prevPresenterUuid = usePrevious(presenterUuid, presenterUuid);
|
const prevPresenterAci = usePrevious(presenterAci, presenterAci);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prevPresenterUuid !== presenterUuid && presenterUuid) {
|
if (prevPresenterAci !== presenterAci && presenterAci) {
|
||||||
switchToPresentationView();
|
switchToPresentationView();
|
||||||
} else if (prevPresenterUuid && !presenterUuid) {
|
} else if (prevPresenterAci && !presenterAci) {
|
||||||
switchFromPresentationView();
|
switchFromPresentationView();
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
presenterUuid,
|
presenterAci,
|
||||||
prevPresenterUuid,
|
prevPresenterAci,
|
||||||
switchToPresentationView,
|
switchToPresentationView,
|
||||||
switchFromPresentationView,
|
switchFromPresentationView,
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -39,6 +39,7 @@ import type { ServiceIdString } from '../types/ServiceId';
|
||||||
import { commonShouldJobContinue } from './helpers/commonShouldJobContinue';
|
import { commonShouldJobContinue } from './helpers/commonShouldJobContinue';
|
||||||
import { sleeper } from '../util/sleeper';
|
import { sleeper } from '../util/sleeper';
|
||||||
import { receiptSchema, ReceiptType } from '../types/Receipt';
|
import { receiptSchema, ReceiptType } from '../types/Receipt';
|
||||||
|
import { serviceIdSchema, aciSchema } from '../types/ServiceId';
|
||||||
import { sendResendRequest } from './helpers/sendResendRequest';
|
import { sendResendRequest } from './helpers/sendResendRequest';
|
||||||
import { sendNullMessage } from './helpers/sendNullMessage';
|
import { sendNullMessage } from './helpers/sendNullMessage';
|
||||||
import { sendSenderKeyDistribution } from './helpers/sendSenderKeyDistribution';
|
import { sendSenderKeyDistribution } from './helpers/sendSenderKeyDistribution';
|
||||||
|
@ -82,12 +83,7 @@ const deleteStoryForEveryoneJobDataSchema = z.object({
|
||||||
updatedStoryRecipients: z
|
updatedStoryRecipients: z
|
||||||
.array(
|
.array(
|
||||||
z.object({
|
z.object({
|
||||||
// TODO: DESKTOP-5630
|
destinationServiceId: serviceIdSchema.optional(),
|
||||||
destinationUuid: z.string().optional(),
|
|
||||||
legacyDestinationUuid: z.string().optional(),
|
|
||||||
|
|
||||||
destinationAci: z.string().optional(),
|
|
||||||
destinationPni: z.string().optional(),
|
|
||||||
distributionListIds: z.array(z.string()),
|
distributionListIds: z.array(z.string()),
|
||||||
isAllowedToReply: z.boolean(),
|
isAllowedToReply: z.boolean(),
|
||||||
})
|
})
|
||||||
|
@ -162,7 +158,7 @@ const resendRequestJobDataSchema = z.object({
|
||||||
plaintext: z.string(),
|
plaintext: z.string(),
|
||||||
receivedAtCounter: z.number(),
|
receivedAtCounter: z.number(),
|
||||||
receivedAtDate: z.number(),
|
receivedAtDate: z.number(),
|
||||||
senderUuid: z.string(),
|
senderAci: aciSchema,
|
||||||
senderDevice: z.number(),
|
senderDevice: z.number(),
|
||||||
timestamp: z.number(),
|
timestamp: z.number(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { assertDev } from '../../util/assert';
|
||||||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import type { ConversationAttributesType } from '../../model-types.d';
|
import type { ConversationAttributesType } from '../../model-types.d';
|
||||||
|
import { isAciString } from '../../types/ServiceId';
|
||||||
import type { reportSpamJobQueue } from '../reportSpamJobQueue';
|
import type { reportSpamJobQueue } from '../reportSpamJobQueue';
|
||||||
|
|
||||||
export async function addReportSpamJob({
|
export async function addReportSpamJob({
|
||||||
|
@ -13,7 +14,10 @@ export async function addReportSpamJob({
|
||||||
jobQueue,
|
jobQueue,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
conversation: Readonly<
|
conversation: Readonly<
|
||||||
Pick<ConversationAttributesType, 'id' | 'type' | 'uuid' | 'reportingToken'>
|
Pick<
|
||||||
|
ConversationAttributesType,
|
||||||
|
'id' | 'type' | 'serviceId' | 'reportingToken'
|
||||||
|
>
|
||||||
>;
|
>;
|
||||||
getMessageServerGuidsForSpam: (
|
getMessageServerGuidsForSpam: (
|
||||||
conversationId: string
|
conversationId: string
|
||||||
|
@ -25,10 +29,10 @@ export async function addReportSpamJob({
|
||||||
'addReportSpamJob: cannot report spam for non-direct conversations'
|
'addReportSpamJob: cannot report spam for non-direct conversations'
|
||||||
);
|
);
|
||||||
|
|
||||||
const { uuid } = conversation;
|
const { serviceId: aci } = conversation;
|
||||||
if (!uuid) {
|
if (!aci || !isAciString(aci)) {
|
||||||
log.info(
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -44,5 +48,5 @@ export async function addReportSpamJob({
|
||||||
return;
|
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,
|
destination: undefined,
|
||||||
destinationServiceId,
|
destinationServiceId,
|
||||||
storyMessageRecipients: updatedStoryRecipients?.map(
|
storyMessageRecipients: updatedStoryRecipients?.map(
|
||||||
({ destinationUuid: legacyDestinationUuid, ...rest }) => {
|
({ destinationServiceId: legacyDestinationUuid, ...rest }) => {
|
||||||
return {
|
return {
|
||||||
// The field was renamed.
|
// The field was renamed.
|
||||||
legacyDestinationUuid,
|
legacyDestinationUuid,
|
||||||
|
|
|
@ -559,12 +559,11 @@ async function getMessageSendData({
|
||||||
});
|
});
|
||||||
|
|
||||||
const storyReaction = message.get('storyReaction');
|
const storyReaction = message.get('storyReaction');
|
||||||
const storySourceUuid = storyMessage?.get('sourceUuid');
|
const storySourceServiceId = storyMessage?.get('sourceServiceId');
|
||||||
|
|
||||||
let reactionForSend: ReactionType | undefined;
|
let reactionForSend: ReactionType | undefined;
|
||||||
if (storyReaction) {
|
if (storyReaction) {
|
||||||
const { targetAuthorUuid: targetAuthorAci, ...restOfReaction } =
|
const { targetAuthorAci, ...restOfReaction } = storyReaction;
|
||||||
storyReaction;
|
|
||||||
|
|
||||||
reactionForSend = {
|
reactionForSend = {
|
||||||
...restOfReaction,
|
...restOfReaction,
|
||||||
|
@ -592,9 +591,9 @@ async function getMessageSendData({
|
||||||
storyMessage,
|
storyMessage,
|
||||||
storyContext: storyMessage
|
storyContext: storyMessage
|
||||||
? {
|
? {
|
||||||
authorAci: storySourceUuid
|
authorAci: storySourceServiceId
|
||||||
? normalizeAci(
|
? normalizeAci(
|
||||||
storySourceUuid,
|
storySourceServiceId,
|
||||||
'sendNormalMessage.storyContext.authorAci'
|
'sendNormalMessage.storyContext.authorAci'
|
||||||
)
|
)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
@ -716,11 +715,8 @@ async function uploadMessageQuote(
|
||||||
return {
|
return {
|
||||||
isGiftBadge: loadedQuote.isGiftBadge,
|
isGiftBadge: loadedQuote.isGiftBadge,
|
||||||
id: loadedQuote.id,
|
id: loadedQuote.id,
|
||||||
authorAci: loadedQuote.authorUuid
|
authorAci: loadedQuote.authorAci
|
||||||
? normalizeAci(
|
? normalizeAci(loadedQuote.authorAci, 'sendNormalMessage.quote.authorAci')
|
||||||
loadedQuote.authorUuid,
|
|
||||||
'sendNormalMessage.quote.authorUuid'
|
|
||||||
)
|
|
||||||
: undefined,
|
: undefined,
|
||||||
text: loadedQuote.text,
|
text: loadedQuote.text,
|
||||||
bodyRanges: loadedQuote.bodyRanges,
|
bodyRanges: loadedQuote.bodyRanges,
|
||||||
|
|
|
@ -136,11 +136,8 @@ export async function sendReaction(
|
||||||
? await ourProfileKeyService.get()
|
? await ourProfileKeyService.get()
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const {
|
const { emoji, targetAuthorAci, ...restOfPendingReaction } =
|
||||||
emoji,
|
pendingReaction;
|
||||||
targetAuthorUuid: targetAuthorAci,
|
|
||||||
...restOfPendingReaction
|
|
||||||
} = pendingReaction;
|
|
||||||
|
|
||||||
const reactionForSend = {
|
const reactionForSend = {
|
||||||
...restOfPendingReaction,
|
...restOfPendingReaction,
|
||||||
|
|
|
@ -26,7 +26,6 @@ import { drop } from '../../util/drop';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
import type { DecryptionErrorEventData } from '../../textsecure/messageReceiverEvents';
|
import type { DecryptionErrorEventData } from '../../textsecure/messageReceiverEvents';
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import { isAciString } from '../../types/ServiceId';
|
|
||||||
import { startAutomaticSessionReset } from '../../util/handleRetry';
|
import { startAutomaticSessionReset } from '../../util/handleRetry';
|
||||||
|
|
||||||
function failoverToLocalReset(
|
function failoverToLocalReset(
|
||||||
|
@ -49,9 +48,8 @@ export async function sendResendRequest(
|
||||||
timeRemaining,
|
timeRemaining,
|
||||||
log,
|
log,
|
||||||
}: ConversationQueueJobBundle,
|
}: ConversationQueueJobBundle,
|
||||||
{ senderUuid: senderAci, ...restOfData }: ResendRequestJobData
|
{ senderAci, ...restOfData }: ResendRequestJobData
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
strictAssert(isAciString(senderAci), 'senderUuid is not an ACI');
|
|
||||||
const data = {
|
const data = {
|
||||||
...restOfData,
|
...restOfData,
|
||||||
senderAci,
|
senderAci,
|
||||||
|
@ -90,9 +88,8 @@ export async function sendResendRequest(
|
||||||
// Note: we will send to blocked users, to those still in message request state, etc.
|
// 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.
|
// Any needed blocking should still apply once the decryption error is fixed.
|
||||||
|
|
||||||
const senderUuid = conversation.get('uuid');
|
if (conversation.getAci() !== senderAci) {
|
||||||
if (!senderUuid) {
|
log.error('conversation was missing a aci, cancelling job.');
|
||||||
log.error('conversation was missing a uuid, cancelling job.');
|
|
||||||
failoverToLocalReset(log, data);
|
failoverToLocalReset(log, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +110,7 @@ export async function sendResendRequest(
|
||||||
await handleMessageSend(
|
await handleMessageSend(
|
||||||
messaging.sendMessageProtoAndWait({
|
messaging.sendMessageProtoAndWait({
|
||||||
timestamp,
|
timestamp,
|
||||||
recipients: [senderUuid],
|
recipients: [senderAci],
|
||||||
proto: plaintext,
|
proto: plaintext,
|
||||||
contentHint: ContentHint.DEFAULT,
|
contentHint: ContentHint.DEFAULT,
|
||||||
groupId,
|
groupId,
|
||||||
|
@ -141,7 +138,7 @@ export async function sendResendRequest(
|
||||||
receivedAt: receivedAtDate,
|
receivedAt: receivedAtDate,
|
||||||
receivedAtCounter,
|
receivedAtCounter,
|
||||||
sentAt: timestamp,
|
sentAt: timestamp,
|
||||||
senderUuid,
|
senderAci,
|
||||||
wasOpened,
|
wasOpened,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -162,7 +159,7 @@ export async function sendResendRequest(
|
||||||
await conversation.addDeliveryIssue({
|
await conversation.addDeliveryIssue({
|
||||||
receivedAt: receivedAtDate,
|
receivedAt: receivedAtDate,
|
||||||
receivedAtCounter,
|
receivedAtCounter,
|
||||||
senderUuid,
|
senderAci,
|
||||||
sentAt: timestamp,
|
sentAt: timestamp,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
@ -57,10 +57,10 @@ export async function sendSavedProto(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid = conversation.get('uuid');
|
const serviceId = conversation.getServiceId();
|
||||||
if (!uuid) {
|
if (!serviceId) {
|
||||||
log.info(
|
log.info(
|
||||||
`conversation ${conversation.idForLogging()} was missing uuid, cancelling job.`
|
`conversation ${conversation.idForLogging()} was missing serviceId, cancelling job.`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ export async function sendSavedProto(
|
||||||
groupId,
|
groupId,
|
||||||
options: sendOptions,
|
options: sendOptions,
|
||||||
proto,
|
proto,
|
||||||
recipients: [uuid],
|
recipients: [serviceId],
|
||||||
timestamp: originalTimestamp,
|
timestamp: originalTimestamp,
|
||||||
urgent,
|
urgent,
|
||||||
story,
|
story,
|
||||||
|
|
|
@ -206,7 +206,7 @@ export async function sendStory(
|
||||||
serviceId: ServiceIdString,
|
serviceId: ServiceIdString,
|
||||||
canReply?: boolean
|
canReply?: boolean
|
||||||
): void {
|
): void {
|
||||||
if (conversation.get('uuid') === serviceId) {
|
if (conversation.getServiceId() === serviceId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import { chunk } from 'lodash';
|
import { chunk } from 'lodash';
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
|
import type { AciString } from '../../types/ServiceId';
|
||||||
import { normalizeAci } from '../../types/ServiceId';
|
import { normalizeAci } from '../../types/ServiceId';
|
||||||
import { getSendOptions } from '../../util/getSendOptions';
|
import { getSendOptions } from '../../util/getSendOptions';
|
||||||
import type { SendTypesType } from '../../util/handleMessageSend';
|
import type { SendTypesType } from '../../util/handleMessageSend';
|
||||||
|
@ -21,7 +22,7 @@ const CHUNK_SIZE = 100;
|
||||||
export type SyncType = {
|
export type SyncType = {
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
senderE164?: string;
|
senderE164?: string;
|
||||||
senderUuid?: string;
|
senderAci?: AciString;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
};
|
};
|
||||||
export enum SyncTypeList {
|
export enum SyncTypeList {
|
||||||
|
@ -41,13 +42,18 @@ export function parseRawSyncDataArray(value: unknown): Array<SyncType> {
|
||||||
return value.map((item: unknown) => {
|
return value.map((item: unknown) => {
|
||||||
strictAssert(isRecord(item), 'sync is not an object');
|
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');
|
strictAssert(typeof timestamp === 'number', 'timestamp should be a number');
|
||||||
|
|
||||||
|
const rawSenderAci = parseOptionalString('senderAci', item.senderAci);
|
||||||
|
const senderAci = rawSenderAci
|
||||||
|
? normalizeAci(rawSenderAci, 'parseRawSyncDataArray')
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
messageId: parseOptionalString('messageId', messageId),
|
messageId: parseOptionalString('messageId', messageId),
|
||||||
senderE164: parseOptionalString('senderE164', senderE164),
|
senderE164: parseOptionalString('senderE164', senderE164),
|
||||||
senderUuid: parseOptionalString('senderUuid', senderUuid),
|
senderAci,
|
||||||
timestamp,
|
timestamp,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -148,11 +154,11 @@ export async function runSyncJob({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const aciSyncs = syncs.map(({ senderUuid, ...rest }) => {
|
const aciSyncs = syncs.map(({ senderAci, ...rest }) => {
|
||||||
return {
|
return {
|
||||||
...rest,
|
...rest,
|
||||||
senderAci: senderUuid
|
senderAci: senderAci
|
||||||
? normalizeAci(senderUuid, 'syncHelpers.senderUuid')
|
? normalizeAci(senderAci, 'syncHelpers.senderAci')
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { strictAssert } from '../util/assert';
|
||||||
import { waitForOnline } from '../util/waitForOnline';
|
import { waitForOnline } from '../util/waitForOnline';
|
||||||
import { isDone as isDeviceLinked } from '../util/registration';
|
import { isDone as isDeviceLinked } from '../util/registration';
|
||||||
import type { LoggerType } from '../types/Logging';
|
import type { LoggerType } from '../types/Logging';
|
||||||
|
import { aciSchema } from '../types/ServiceId';
|
||||||
import { map } from '../util/iterables';
|
import { map } from '../util/iterables';
|
||||||
|
|
||||||
import { JobQueue } from './JobQueue';
|
import { JobQueue } from './JobQueue';
|
||||||
|
@ -27,7 +28,7 @@ const isRetriable4xxStatus = (code: number): boolean =>
|
||||||
RETRYABLE_4XX_FAILURE_STATUSES.has(code);
|
RETRYABLE_4XX_FAILURE_STATUSES.has(code);
|
||||||
|
|
||||||
const reportSpamJobDataSchema = z.object({
|
const reportSpamJobDataSchema = z.object({
|
||||||
uuid: z.string().min(1),
|
aci: aciSchema,
|
||||||
token: z.string().optional(),
|
token: z.string().optional(),
|
||||||
serverGuids: z.string().array().min(1).max(1000),
|
serverGuids: z.string().array().min(1).max(1000),
|
||||||
});
|
});
|
||||||
|
@ -49,7 +50,7 @@ export class ReportSpamJobQueue extends JobQueue<ReportSpamJobData> {
|
||||||
{ data }: Readonly<{ data: ReportSpamJobData }>,
|
{ data }: Readonly<{ data: ReportSpamJobData }>,
|
||||||
{ log }: Readonly<{ log: LoggerType }>
|
{ log }: Readonly<{ log: LoggerType }>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { uuid: senderUuid, token, serverGuids } = data;
|
const { aci: senderAci, token, serverGuids } = data;
|
||||||
|
|
||||||
await new Promise<void>(resolve => {
|
await new Promise<void>(resolve => {
|
||||||
window.storage.onready(resolve);
|
window.storage.onready(resolve);
|
||||||
|
@ -68,7 +69,7 @@ export class ReportSpamJobQueue extends JobQueue<ReportSpamJobData> {
|
||||||
try {
|
try {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
map(serverGuids, serverGuid =>
|
map(serverGuids, serverGuid =>
|
||||||
server.reportMessage({ senderUuid, serverGuid, token })
|
server.reportMessage({ senderAci, serverGuid, token })
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
||||||
|
|
||||||
const {
|
const {
|
||||||
contentHint,
|
contentHint,
|
||||||
identifier,
|
serviceId,
|
||||||
isSyncMessage,
|
isSyncMessage,
|
||||||
messageIds = [],
|
messageIds = [],
|
||||||
protoBase64,
|
protoBase64,
|
||||||
|
@ -75,14 +75,12 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
||||||
urgent,
|
urgent,
|
||||||
} = data;
|
} = data;
|
||||||
log.info(
|
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) {
|
if (!conversation) {
|
||||||
throw new Error(
|
throw new Error(`Failed to get conversation for serviceId ${serviceId}`);
|
||||||
`Failed to get conversation for identifier ${identifier}`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isConversationAccepted(conversation.attributes)) {
|
if (!isConversationAccepted(conversation.attributes)) {
|
||||||
|
@ -103,13 +101,6 @@ export class SingleProtoJobQueue extends JobQueue<SingleProtoJobData> {
|
||||||
);
|
);
|
||||||
return;
|
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 proto = Proto.Content.decode(Bytes.fromBase64(protoBase64));
|
||||||
const options = await getSendOptions(conversation.attributes, {
|
const options = await getSendOptions(conversation.attributes, {
|
||||||
|
|
|
@ -28,7 +28,7 @@ export function forMessage(
|
||||||
| 'editMessageTimestamp'
|
| 'editMessageTimestamp'
|
||||||
| 'sent_at'
|
| 'sent_at'
|
||||||
| 'source'
|
| 'source'
|
||||||
| 'sourceUuid'
|
| 'sourceServiceId'
|
||||||
| 'timestamp'
|
| 'timestamp'
|
||||||
| 'type'
|
| 'type'
|
||||||
>
|
>
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {
|
||||||
import type { DeleteSentProtoRecipientOptionsType } from '../sql/Interface';
|
import type { DeleteSentProtoRecipientOptionsType } from '../sql/Interface';
|
||||||
import dataInterface from '../sql/Client';
|
import dataInterface from '../sql/Client';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { getSourceUuid } from '../messages/helpers';
|
import { getSourceServiceId } from '../messages/helpers';
|
||||||
import { queueUpdateMessage } from '../util/messageBatcher';
|
import { queueUpdateMessage } from '../util/messageBatcher';
|
||||||
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
import { getMessageSentTimestamp } from '../util/getMessageSentTimestamp';
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ const deleteSentProtoBatcher = createWaitBatcher({
|
||||||
items
|
items
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const uuid of successfulPhoneNumberShares) {
|
for (const serviceId of successfulPhoneNumberShares) {
|
||||||
const convo = window.ConversationController.get(uuid);
|
const convo = window.ConversationController.get(serviceId);
|
||||||
if (!convo) {
|
if (!convo) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -158,8 +158,8 @@ export class MessageReceipts extends Collection<MessageReceiptModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||||
const sourceUuid = getSourceUuid(message.attributes);
|
const sourceServiceId = getSourceServiceId(message.attributes);
|
||||||
if (ourAci !== sourceUuid) {
|
if (ourAci !== sourceServiceId) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ export class MessageReceipts extends Collection<MessageReceiptModel> {
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
log.warn(
|
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')) {
|
if (conversation.getServiceId()) {
|
||||||
const syncByUuid = this.findWhere({
|
const syncByAci = this.findWhere({
|
||||||
threadAci: conversation.get('uuid'),
|
threadAci: conversation.getServiceId(),
|
||||||
});
|
});
|
||||||
if (syncByUuid) {
|
if (syncByAci) {
|
||||||
log.info(
|
log.info(
|
||||||
`Found early message request response for UUID ${conversation.idForLogging()}`
|
`Found early message request response for aci ${conversation.idForLogging()}`
|
||||||
);
|
);
|
||||||
this.remove(syncByUuid);
|
this.remove(syncByAci);
|
||||||
return syncByUuid;
|
return syncByAci;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ export class MessageRequests extends Collection<MessageRequestModel> {
|
||||||
if (!conversation && (threadE164 || threadAci)) {
|
if (!conversation && (threadE164 || threadAci)) {
|
||||||
conversation = window.ConversationController.lookupOrCreate({
|
conversation = window.ConversationController.lookupOrCreate({
|
||||||
e164: threadE164,
|
e164: threadE164,
|
||||||
uuid: threadAci,
|
serviceId: threadAci,
|
||||||
reason: 'MessageRequests.onResponse',
|
reason: 'MessageRequests.onResponse',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class Reactions extends Collection<ReactionModel> {
|
||||||
const senderId = getContactId(message.attributes);
|
const senderId = getContactId(message.attributes);
|
||||||
const reactionsBySource = this.filter(re => {
|
const reactionsBySource = this.filter(re => {
|
||||||
const targetSender = window.ConversationController.lookupOrCreate({
|
const targetSender = window.ConversationController.lookupOrCreate({
|
||||||
uuid: re.get('targetAuthorUuid'),
|
serviceId: re.get('targetAuthorAci'),
|
||||||
reason: 'Reactions.forMessage',
|
reason: 'Reactions.forMessage',
|
||||||
});
|
});
|
||||||
const targetTimestamp = re.get('targetTimestamp');
|
const targetTimestamp = re.get('targetTimestamp');
|
||||||
|
@ -92,7 +92,7 @@ export class Reactions extends Collection<ReactionModel> {
|
||||||
// to to figure that out.
|
// to to figure that out.
|
||||||
const targetAuthorConversation =
|
const targetAuthorConversation =
|
||||||
window.ConversationController.lookupOrCreate({
|
window.ConversationController.lookupOrCreate({
|
||||||
uuid: reaction.get('targetAuthorUuid'),
|
serviceId: reaction.get('targetAuthorAci'),
|
||||||
reason: 'Reactions.onReaction',
|
reason: 'Reactions.onReaction',
|
||||||
});
|
});
|
||||||
const targetConversationId = targetAuthorConversation?.id;
|
const targetConversationId = targetAuthorConversation?.id;
|
||||||
|
@ -122,7 +122,7 @@ export class Reactions extends Collection<ReactionModel> {
|
||||||
'No message for reaction',
|
'No message for reaction',
|
||||||
reaction.get('timestamp'),
|
reaction.get('timestamp'),
|
||||||
'targeting',
|
'targeting',
|
||||||
reaction.get('targetAuthorUuid'),
|
reaction.get('targetAuthorAci'),
|
||||||
reaction.get('targetTimestamp')
|
reaction.get('targetTimestamp')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ export class Reactions extends Collection<ReactionModel> {
|
||||||
if (!targetConversation) {
|
if (!targetConversation) {
|
||||||
log.info(
|
log.info(
|
||||||
'No target conversation for reaction',
|
'No target conversation for reaction',
|
||||||
reaction.get('targetAuthorUuid'),
|
reaction.get('targetAuthorAci'),
|
||||||
reaction.get('targetTimestamp')
|
reaction.get('targetTimestamp')
|
||||||
);
|
);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -48,7 +48,7 @@ async function maybeItIsAReactionReadSync(sync: ReadSyncModel): Promise<void> {
|
||||||
notificationService.removeBy({
|
notificationService.removeBy({
|
||||||
conversationId: readReaction.conversationId,
|
conversationId: readReaction.conversationId,
|
||||||
emoji: readReaction.emoji,
|
emoji: readReaction.emoji,
|
||||||
targetAuthorUuid: readReaction.targetAuthorUuid,
|
targetAuthorAci: readReaction.targetAuthorAci,
|
||||||
targetTimestamp: readReaction.targetTimestamp,
|
targetTimestamp: readReaction.targetTimestamp,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ export class ReadSyncs extends Collection {
|
||||||
forMessage(message: MessageModel): ReadSyncModel | null {
|
forMessage(message: MessageModel): ReadSyncModel | null {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
e164: message.get('source'),
|
e164: message.get('source'),
|
||||||
uuid: message.get('sourceUuid'),
|
serviceId: message.get('sourceServiceId'),
|
||||||
reason: 'ReadSyncs.forMessage',
|
reason: 'ReadSyncs.forMessage',
|
||||||
});
|
});
|
||||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||||
|
@ -95,7 +95,7 @@ export class ReadSyncs extends Collection {
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
e164: item.source,
|
e164: item.source,
|
||||||
uuid: item.sourceUuid,
|
serviceId: item.sourceServiceId,
|
||||||
reason: 'ReadSyncs.onSync',
|
reason: 'ReadSyncs.onSync',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -29,16 +29,16 @@ export class ViewOnceOpenSyncs extends Collection<ViewOnceOpenSyncModel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
forMessage(message: MessageModel): ViewOnceOpenSyncModel | null {
|
forMessage(message: MessageModel): ViewOnceOpenSyncModel | null {
|
||||||
const syncBySourceUuid = this.find(item => {
|
const syncBySourceAci = this.find(item => {
|
||||||
return (
|
return (
|
||||||
item.get('sourceAci') === message.get('sourceUuid') &&
|
item.get('sourceAci') === message.get('sourceServiceId') &&
|
||||||
item.get('timestamp') === message.get('sent_at')
|
item.get('timestamp') === message.get('sent_at')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (syncBySourceUuid) {
|
if (syncBySourceAci) {
|
||||||
log.info('Found early view once open sync for message');
|
log.info('Found early view once open sync for message');
|
||||||
this.remove(syncBySourceUuid);
|
this.remove(syncBySourceAci);
|
||||||
return syncBySourceUuid;
|
return syncBySourceAci;
|
||||||
}
|
}
|
||||||
|
|
||||||
const syncBySource = this.find(item => {
|
const syncBySource = this.find(item => {
|
||||||
|
@ -63,7 +63,7 @@ export class ViewOnceOpenSyncs extends Collection<ViewOnceOpenSyncModel> {
|
||||||
);
|
);
|
||||||
|
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const itemSourceAci = item.sourceUuid;
|
const itemSourceAci = item.sourceServiceId;
|
||||||
const syncSourceAci = sync.get('sourceAci');
|
const syncSourceAci = sync.get('sourceAci');
|
||||||
const itemSource = item.source;
|
const itemSource = item.source;
|
||||||
const syncSource = sync.get('source');
|
const syncSource = sync.get('source');
|
||||||
|
|
|
@ -43,7 +43,7 @@ export class ViewSyncs extends Collection {
|
||||||
forMessage(message: MessageModel): Array<ViewSyncModel> {
|
forMessage(message: MessageModel): Array<ViewSyncModel> {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
e164: message.get('source'),
|
e164: message.get('source'),
|
||||||
uuid: message.get('sourceUuid'),
|
serviceId: message.get('sourceServiceId'),
|
||||||
reason: 'ViewSyncs.forMessage',
|
reason: 'ViewSyncs.forMessage',
|
||||||
});
|
});
|
||||||
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
const messageTimestamp = getMessageSentTimestamp(message.attributes, {
|
||||||
|
@ -73,7 +73,7 @@ export class ViewSyncs extends Collection {
|
||||||
const found = messages.find(item => {
|
const found = messages.find(item => {
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
e164: item.source,
|
e164: item.source,
|
||||||
uuid: item.sourceUuid,
|
serviceId: item.sourceServiceId,
|
||||||
reason: 'ViewSyncs.onSync',
|
reason: 'ViewSyncs.onSync',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -111,16 +111,16 @@ export function getPaymentEventDescription(
|
||||||
export function isQuoteAMatch(
|
export function isQuoteAMatch(
|
||||||
message: MessageAttributesType | null | undefined,
|
message: MessageAttributesType | null | undefined,
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
quote: Pick<QuotedMessageType, 'id' | 'authorUuid' | 'author'>
|
quote: Pick<QuotedMessageType, 'id' | 'authorAci' | 'author'>
|
||||||
): message is MessageAttributesType {
|
): message is MessageAttributesType {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { authorUuid, id } = quote;
|
const { authorAci, id } = quote;
|
||||||
const authorConversation = window.ConversationController.lookupOrCreate({
|
const authorConversation = window.ConversationController.lookupOrCreate({
|
||||||
e164: 'author' in quote ? quote.author : undefined,
|
e164: 'author' in quote ? quote.author : undefined,
|
||||||
uuid: authorUuid,
|
serviceId: authorAci,
|
||||||
reason: 'helpers.isQuoteAMatch',
|
reason: 'helpers.isQuoteAMatch',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -137,18 +137,18 @@ export function isQuoteAMatch(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContactId(
|
export function getContactId(
|
||||||
message: Pick<MessageAttributesType, 'type' | 'source' | 'sourceUuid'>
|
message: Pick<MessageAttributesType, 'type' | 'source' | 'sourceServiceId'>
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const source = getSource(message);
|
const source = getSource(message);
|
||||||
const sourceUuid = getSourceUuid(message);
|
const sourceServiceId = getSourceServiceId(message);
|
||||||
|
|
||||||
if (!source && !sourceUuid) {
|
if (!source && !sourceServiceId) {
|
||||||
return window.ConversationController.getOurConversationId();
|
return window.ConversationController.getOurConversationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.lookupOrCreate({
|
||||||
e164: source,
|
e164: source,
|
||||||
uuid: sourceUuid,
|
serviceId: sourceServiceId,
|
||||||
reason: 'helpers.getContactId',
|
reason: 'helpers.getContactId',
|
||||||
});
|
});
|
||||||
return conversation?.id;
|
return conversation?.id;
|
||||||
|
@ -191,15 +191,15 @@ export function getSourceDevice(
|
||||||
return sourceDevice || window.textsecure.storage.user.getDeviceId();
|
return sourceDevice || window.textsecure.storage.user.getDeviceId();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSourceUuid(
|
export function getSourceServiceId(
|
||||||
message: Pick<MessageAttributesType, 'type' | 'sourceUuid'>
|
message: Pick<MessageAttributesType, 'type' | 'sourceServiceId'>
|
||||||
): ServiceIdString | undefined {
|
): ServiceIdString | undefined {
|
||||||
if (isIncoming(message) || isStory(message)) {
|
if (isIncoming(message) || isStory(message)) {
|
||||||
return message.sourceUuid;
|
return message.sourceServiceId;
|
||||||
}
|
}
|
||||||
if (!isOutgoing(message)) {
|
if (!isOutgoing(message)) {
|
||||||
log.warn(
|
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 = {
|
export type SenderKeyDeviceType = {
|
||||||
id: number;
|
id: number;
|
||||||
identifier: string;
|
serviceId: ServiceIdString;
|
||||||
registrationId: number;
|
registrationId: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ export type CustomError = Error & {
|
||||||
export type GroupMigrationType = {
|
export type GroupMigrationType = {
|
||||||
areWeInvited: boolean;
|
areWeInvited: boolean;
|
||||||
droppedMemberIds: Array<string>;
|
droppedMemberIds: Array<string>;
|
||||||
invitedMembers: Array<GroupV2PendingMemberType>;
|
invitedMembers: Array<LegacyMigrationPendingMemberType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type QuotedAttachment = {
|
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
|
// `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.
|
// new messages, but old messages might have this attribute.
|
||||||
author?: string;
|
author?: string;
|
||||||
authorUuid?: string;
|
authorAci?: AciString;
|
||||||
bodyRanges?: ReadonlyArray<RawBodyRange>;
|
bodyRanges?: ReadonlyArray<RawBodyRange>;
|
||||||
id: number;
|
id: number;
|
||||||
isGiftBadge?: boolean;
|
isGiftBadge?: boolean;
|
||||||
|
@ -98,17 +98,10 @@ export type QuotedMessageType = {
|
||||||
|
|
||||||
type StoryReplyContextType = {
|
type StoryReplyContextType = {
|
||||||
attachment?: AttachmentType;
|
attachment?: AttachmentType;
|
||||||
authorUuid?: string;
|
authorAci?: AciString;
|
||||||
messageId: string;
|
messageId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RetryOptions = Readonly<{
|
|
||||||
type: 'session-reset';
|
|
||||||
uuid: string;
|
|
||||||
e164: string;
|
|
||||||
now: number;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export type GroupV1Update = {
|
export type GroupV1Update = {
|
||||||
avatarUpdated?: boolean;
|
avatarUpdated?: boolean;
|
||||||
joined?: Array<string>;
|
joined?: Array<string>;
|
||||||
|
@ -119,7 +112,7 @@ export type GroupV1Update = {
|
||||||
export type MessageReactionType = {
|
export type MessageReactionType = {
|
||||||
emoji: undefined | string;
|
emoji: undefined | string;
|
||||||
fromId: string;
|
fromId: string;
|
||||||
targetAuthorUuid: AciString;
|
targetAuthorAci: AciString;
|
||||||
targetTimestamp: number;
|
targetTimestamp: number;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
isSentByConversationId?: Record<string, boolean>;
|
isSentByConversationId?: Record<string, boolean>;
|
||||||
|
@ -169,7 +162,6 @@ export type MessageAttributesType = {
|
||||||
quote?: QuotedMessageType;
|
quote?: QuotedMessageType;
|
||||||
reactions?: ReadonlyArray<MessageReactionType>;
|
reactions?: ReadonlyArray<MessageReactionType>;
|
||||||
requiredProtocolVersion?: number;
|
requiredProtocolVersion?: number;
|
||||||
retryOptions?: RetryOptions;
|
|
||||||
sourceDevice?: number;
|
sourceDevice?: number;
|
||||||
storyDistributionListId?: StoryDistributionIdString;
|
storyDistributionListId?: StoryDistributionIdString;
|
||||||
storyId?: string;
|
storyId?: string;
|
||||||
|
@ -210,7 +202,7 @@ export type MessageAttributesType = {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
storyReaction?: {
|
storyReaction?: {
|
||||||
emoji: string;
|
emoji: string;
|
||||||
targetAuthorUuid: AciString;
|
targetAuthorAci: AciString;
|
||||||
targetTimestamp: number;
|
targetTimestamp: number;
|
||||||
};
|
};
|
||||||
giftBadge?: {
|
giftBadge?: {
|
||||||
|
@ -225,7 +217,7 @@ export type MessageAttributesType = {
|
||||||
expireTimer?: DurationInSeconds;
|
expireTimer?: DurationInSeconds;
|
||||||
fromSync?: unknown;
|
fromSync?: unknown;
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
};
|
};
|
||||||
conversationMerge?: {
|
conversationMerge?: {
|
||||||
renderInfo: ConversationRenderInfoType;
|
renderInfo: ConversationRenderInfoType;
|
||||||
|
@ -249,12 +241,12 @@ export type MessageAttributesType = {
|
||||||
serverGuid?: string;
|
serverGuid?: string;
|
||||||
serverTimestamp?: number;
|
serverTimestamp?: number;
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
|
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
|
||||||
// Backwards-compatibility with prerelease data schema
|
// Backwards-compatibility with prerelease data schema
|
||||||
invitedGV2Members?: Array<GroupV2PendingMemberType>;
|
invitedGV2Members?: Array<LegacyMigrationPendingMemberType>;
|
||||||
droppedGV2MemberIds?: Array<string>;
|
droppedGV2MemberIds?: Array<string>;
|
||||||
|
|
||||||
sendHQImages?: boolean;
|
sendHQImages?: boolean;
|
||||||
|
@ -283,7 +275,7 @@ export type ConversationLastProfileType = Readonly<{
|
||||||
|
|
||||||
export type ValidateConversationType = Pick<
|
export type ValidateConversationType = Pick<
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
'e164' | 'uuid' | 'type' | 'groupId'
|
'e164' | 'serviceId' | 'type' | 'groupId'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type DraftEditMessageType = {
|
export type DraftEditMessageType = {
|
||||||
|
@ -378,7 +370,7 @@ export type ConversationAttributesType = {
|
||||||
version: number;
|
version: number;
|
||||||
|
|
||||||
// Private core info
|
// Private core info
|
||||||
uuid?: ServiceIdString;
|
serviceId?: ServiceIdString;
|
||||||
pni?: PniString;
|
pni?: PniString;
|
||||||
e164?: string;
|
e164?: string;
|
||||||
|
|
||||||
|
@ -470,7 +462,7 @@ export type ConversationRenderInfoType = Pick<
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type GroupV2MemberType = {
|
export type GroupV2MemberType = {
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
role: MemberRoleEnum;
|
role: MemberRoleEnum;
|
||||||
joinedAtVersion: number;
|
joinedAtVersion: number;
|
||||||
|
|
||||||
|
@ -481,20 +473,27 @@ export type GroupV2MemberType = {
|
||||||
approvedByAdmin?: boolean;
|
approvedByAdmin?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LegacyMigrationPendingMemberType = {
|
||||||
|
addedByUserId?: string;
|
||||||
|
uuid: string;
|
||||||
|
timestamp: number;
|
||||||
|
role: MemberRoleEnum;
|
||||||
|
};
|
||||||
|
|
||||||
export type GroupV2PendingMemberType = {
|
export type GroupV2PendingMemberType = {
|
||||||
addedByUserId?: AciString;
|
addedByUserId?: AciString;
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
role: MemberRoleEnum;
|
role: MemberRoleEnum;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GroupV2BannedMemberType = {
|
export type GroupV2BannedMemberType = {
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GroupV2PendingAdminApprovalType = {
|
export type GroupV2PendingAdminApprovalType = {
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -517,7 +516,7 @@ export type ReactionAttributesType = {
|
||||||
// Necessary to put 1:1 story replies into the right conversation - not the same
|
// Necessary to put 1:1 story replies into the right conversation - not the same
|
||||||
// conversation as the target message!
|
// conversation as the target message!
|
||||||
storyReactionMessage?: MessageModel;
|
storyReactionMessage?: MessageModel;
|
||||||
targetAuthorUuid: AciString;
|
targetAuthorAci: AciString;
|
||||||
targetTimestamp: number;
|
targetTimestamp: number;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,7 +82,6 @@ import type { DraftBodyRanges } from '../types/BodyRange';
|
||||||
import { BodyRange } from '../types/BodyRange';
|
import { BodyRange } from '../types/BodyRange';
|
||||||
import { migrateColor } from '../util/migrateColor';
|
import { migrateColor } from '../util/migrateColor';
|
||||||
import { isNotNil } from '../util/isNotNil';
|
import { isNotNil } from '../util/isNotNil';
|
||||||
import { resolveSenderKeyDevice } from '../util/resolveSenderKeyDevice';
|
|
||||||
import {
|
import {
|
||||||
NotificationType,
|
NotificationType,
|
||||||
notificationService,
|
notificationService,
|
||||||
|
@ -304,15 +303,16 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
// Note that we intentionally don't use `initialize()` method because it
|
// Note that we intentionally don't use `initialize()` method because it
|
||||||
// isn't compatible with esnext output of esbuild.
|
// isn't compatible with esnext output of esbuild.
|
||||||
const uuid = this.get('uuid');
|
const serviceId = this.getServiceId();
|
||||||
const normalizedServiceId =
|
const normalizedServiceId =
|
||||||
uuid && normalizeServiceId(uuid, 'ConversationModel.initialize');
|
serviceId &&
|
||||||
if (uuid && normalizedServiceId !== uuid) {
|
normalizeServiceId(serviceId, 'ConversationModel.initialize');
|
||||||
|
if (serviceId && normalizedServiceId !== serviceId) {
|
||||||
log.warn(
|
log.warn(
|
||||||
'ConversationModel.initialize: normalizing serviceId from ' +
|
'ConversationModel.initialize: normalizing serviceId from ' +
|
||||||
`${uuid} to ${normalizedServiceId}`
|
`${serviceId} to ${normalizedServiceId}`
|
||||||
);
|
);
|
||||||
this.set('uuid', normalizedServiceId);
|
this.set('serviceId', normalizedServiceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isValidE164(attributes.id, false)) {
|
if (isValidE164(attributes.id, false)) {
|
||||||
|
@ -805,8 +805,8 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
const e164 = this.get('e164');
|
const e164 = this.get('e164');
|
||||||
const pni = this.get('pni');
|
const pni = this.getPni();
|
||||||
const aci = this.get('uuid');
|
const aci = this.getServiceId();
|
||||||
if (e164 && pni && aci && pni !== aci) {
|
if (e164 && pni && aci && pni !== aci) {
|
||||||
this.updateE164(undefined);
|
this.updateE164(undefined);
|
||||||
this.updatePni(undefined);
|
this.updatePni(undefined);
|
||||||
|
@ -878,9 +878,9 @@ export class ConversationModel extends window.Backbone
|
||||||
let blocked = false;
|
let blocked = false;
|
||||||
const wasBlocked = this.isBlocked();
|
const wasBlocked = this.isBlocked();
|
||||||
|
|
||||||
const uuid = this.get('uuid');
|
const serviceId = this.getServiceId();
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
drop(window.storage.blocked.addBlockedUuid(uuid));
|
drop(window.storage.blocked.addBlockedServiceId(serviceId));
|
||||||
blocked = true;
|
blocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -910,9 +910,9 @@ export class ConversationModel extends window.Backbone
|
||||||
let unblocked = false;
|
let unblocked = false;
|
||||||
const wasBlocked = this.isBlocked();
|
const wasBlocked = this.isBlocked();
|
||||||
|
|
||||||
const uuid = this.get('uuid');
|
const serviceId = this.getServiceId();
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
drop(window.storage.blocked.removeBlockedUuid(uuid));
|
drop(window.storage.blocked.removeBlockedServiceId(serviceId));
|
||||||
unblocked = true;
|
unblocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,10 +977,10 @@ export class ConversationModel extends window.Backbone
|
||||||
});
|
});
|
||||||
|
|
||||||
window.reduxActions?.stories.removeAllContactStories(this.id);
|
window.reduxActions?.stories.removeAllContactStories(this.id);
|
||||||
const uuid = this.get('uuid');
|
const serviceId = this.getServiceId();
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
window.reduxActions?.storyDistributionLists.removeMemberFromAllDistributionLists(
|
window.reduxActions?.storyDistributionLists.removeMemberFromAllDistributionLists(
|
||||||
uuid
|
serviceId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,7 +1162,7 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.get('uuid')) {
|
if (!this.getServiceId()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,12 +1353,12 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
async onNewMessage(message: MessageModel): Promise<void> {
|
async onNewMessage(message: MessageModel): Promise<void> {
|
||||||
const uuid = message.get('sourceUuid');
|
const serviceId = message.get('sourceServiceId');
|
||||||
const e164 = message.get('source');
|
const e164 = message.get('source');
|
||||||
const sourceDevice = message.get('sourceDevice');
|
const sourceDevice = message.get('sourceDevice');
|
||||||
|
|
||||||
const source = window.ConversationController.lookupOrCreate({
|
const source = window.ConversationController.lookupOrCreate({
|
||||||
uuid,
|
serviceId,
|
||||||
e164,
|
e164,
|
||||||
reason: 'ConversationModel.onNewMessage',
|
reason: 'ConversationModel.onNewMessage',
|
||||||
});
|
});
|
||||||
|
@ -1855,27 +1855,29 @@ export class ConversationModel extends window.Backbone
|
||||||
this.captureChange('updateE164');
|
this.captureChange('updateE164');
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUuid(uuid?: ServiceIdString): void {
|
updateServiceId(serviceId?: ServiceIdString): void {
|
||||||
const oldValue = this.get('uuid');
|
const oldValue = this.getServiceId();
|
||||||
if (uuid === oldValue) {
|
if (serviceId === oldValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set(
|
this.set(
|
||||||
'uuid',
|
'serviceId',
|
||||||
uuid ? normalizeServiceId(uuid, 'Conversation.updateUuid') : undefined
|
serviceId
|
||||||
|
? normalizeServiceId(serviceId, 'Conversation.updateServiceId')
|
||||||
|
: undefined
|
||||||
);
|
);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
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
|
// 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 case where we need to do old and new PNI comparisons. We'll wait
|
||||||
// for the PNI update to do that.
|
// 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));
|
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.captureChange('updateUuid');
|
this.captureChange('updateServiceId');
|
||||||
}
|
}
|
||||||
|
|
||||||
trackPreviousIdentityKey(publicKey: Uint8Array): void {
|
trackPreviousIdentityKey(publicKey: Uint8Array): void {
|
||||||
|
@ -1902,7 +1904,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePni(pni?: PniString): void {
|
updatePni(pni?: PniString): void {
|
||||||
const oldValue = this.get('pni');
|
const oldValue = this.getPni();
|
||||||
if (pni === oldValue) {
|
if (pni === oldValue) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1913,9 +1915,9 @@ export class ConversationModel extends window.Backbone
|
||||||
);
|
);
|
||||||
|
|
||||||
const pniIsPrimaryId =
|
const pniIsPrimaryId =
|
||||||
!this.get('uuid') ||
|
!this.getServiceId() ||
|
||||||
this.get('uuid') === oldValue ||
|
this.getServiceId() === oldValue ||
|
||||||
this.get('uuid') === pni;
|
this.getServiceId() === pni;
|
||||||
const haveSentMessage = Boolean(
|
const haveSentMessage = Boolean(
|
||||||
this.get('profileSharing') || this.get('sentMessageCount')
|
this.get('profileSharing') || this.get('sentMessageCount')
|
||||||
);
|
);
|
||||||
|
@ -1958,9 +1960,9 @@ export class ConversationModel extends window.Backbone
|
||||||
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue));
|
drop(window.textsecure.storage.protocol.removeIdentityKey(oldValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pni && !this.get('uuid')) {
|
if (pni && !this.getServiceId()) {
|
||||||
log.warn(
|
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,
|
type: conversationQueueJobEnum.enum.Receipts,
|
||||||
conversationId: this.get('id'),
|
conversationId: this.get('id'),
|
||||||
receiptsType: ReceiptType.Read,
|
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,
|
messageId: m.id,
|
||||||
conversationId,
|
conversationId,
|
||||||
senderE164: m.source,
|
senderE164: m.source,
|
||||||
senderUuid: m.sourceUuid,
|
senderAci,
|
||||||
timestamp: getMessageSentTimestamp(m, { log }),
|
timestamp: getMessageSentTimestamp(m, { log }),
|
||||||
isDirectConversation: isDirectConversation(this.attributes),
|
isDirectConversation: isDirectConversation(this.attributes),
|
||||||
})),
|
};
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2266,7 +2273,7 @@ export class ConversationModel extends window.Backbone
|
||||||
this.set({
|
this.set({
|
||||||
pendingAdminApprovalV2: [
|
pendingAdminApprovalV2: [
|
||||||
{
|
{
|
||||||
uuid: ourAci,
|
aci: ourAci,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2828,23 +2835,23 @@ export class ConversationModel extends window.Backbone
|
||||||
async addDeliveryIssue({
|
async addDeliveryIssue({
|
||||||
receivedAt,
|
receivedAt,
|
||||||
receivedAtCounter,
|
receivedAtCounter,
|
||||||
senderUuid,
|
senderAci,
|
||||||
sentAt,
|
sentAt,
|
||||||
}: {
|
}: {
|
||||||
receivedAt: number;
|
receivedAt: number;
|
||||||
receivedAtCounter: number;
|
receivedAtCounter: number;
|
||||||
senderUuid: string;
|
senderAci: AciString;
|
||||||
sentAt: number;
|
sentAt: number;
|
||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
log.info(`addDeliveryIssue: adding for ${this.idForLogging()}`, {
|
log.info(`addDeliveryIssue: adding for ${this.idForLogging()}`, {
|
||||||
sentAt,
|
sentAt,
|
||||||
senderUuid,
|
senderAci,
|
||||||
});
|
});
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
conversationId: this.id,
|
conversationId: this.id,
|
||||||
type: 'delivery-issue',
|
type: 'delivery-issue',
|
||||||
sourceUuid: senderUuid,
|
sourceServiceId: senderAci,
|
||||||
sent_at: receivedAt,
|
sent_at: receivedAt,
|
||||||
received_at: receivedAtCounter,
|
received_at: receivedAtCounter,
|
||||||
received_at_ms: receivedAt,
|
received_at_ms: receivedAt,
|
||||||
|
@ -2945,15 +2952,11 @@ export class ConversationModel extends window.Backbone
|
||||||
if (senderKeyInfo) {
|
if (senderKeyInfo) {
|
||||||
const updatedSenderKeyInfo = {
|
const updatedSenderKeyInfo = {
|
||||||
...senderKeyInfo,
|
...senderKeyInfo,
|
||||||
memberDevices: senderKeyInfo.memberDevices
|
memberDevices: senderKeyInfo.memberDevices.filter(
|
||||||
.map(resolveSenderKeyDevice)
|
({ serviceId: memberServiceId }) => {
|
||||||
.filter(isNotNil)
|
|
||||||
.filter(({ serviceId: memberServiceId }) => {
|
|
||||||
return memberServiceId !== keyChangedId;
|
return memberServiceId !== keyChangedId;
|
||||||
})
|
}
|
||||||
.map(({ serviceId: memberServiceId, ...rest }) => {
|
),
|
||||||
return { identifier: memberServiceId, ...rest };
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.set('senderKeyInfo', updatedSenderKeyInfo);
|
this.set('senderKeyInfo', updatedSenderKeyInfo);
|
||||||
|
@ -3267,7 +3270,7 @@ export class ConversationModel extends window.Backbone
|
||||||
newValue: string
|
newValue: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const sourceServiceId = this.getCheckedServiceId(
|
const sourceServiceId = this.getCheckedServiceId(
|
||||||
'Change number notification without uuid'
|
'Change number notification without service id'
|
||||||
);
|
);
|
||||||
|
|
||||||
const { storage } = window.textsecure;
|
const { storage } = window.textsecure;
|
||||||
|
@ -3299,7 +3302,7 @@ export class ConversationModel extends window.Backbone
|
||||||
return convo.addNotification('change-number-notification', {
|
return convo.addNotification('change-number-notification', {
|
||||||
readStatus: ReadStatus.Read,
|
readStatus: ReadStatus.Read,
|
||||||
seenStatus: SeenStatus.Unseen,
|
seenStatus: SeenStatus.Unseen,
|
||||||
sourceUuid: sourceServiceId,
|
sourceServiceId,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -3379,7 +3382,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
const members = this.get('membersV2') || [];
|
const members = this.get('membersV2') || [];
|
||||||
const member = members.find(x => x.uuid === serviceId);
|
const member = members.find(x => x.aci === serviceId);
|
||||||
if (!member) {
|
if (!member) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3390,7 +3393,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
getServiceId(): ServiceIdString | undefined {
|
getServiceId(): ServiceIdString | undefined {
|
||||||
return this.get('uuid');
|
return this.get('serviceId');
|
||||||
}
|
}
|
||||||
|
|
||||||
getCheckedServiceId(reason: string): ServiceIdString {
|
getCheckedServiceId(reason: string): ServiceIdString {
|
||||||
|
@ -3400,7 +3403,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
getAci(): AciString | undefined {
|
getAci(): AciString | undefined {
|
||||||
const value = this.get('uuid');
|
const value = this.getServiceId();
|
||||||
if (value && isAciString(value)) {
|
if (value && isAciString(value)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -4483,7 +4486,7 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
conversations.map(conversation =>
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid = this.get('uuid');
|
const serviceId = this.getServiceId();
|
||||||
if (!uuid) {
|
if (!serviceId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4663,7 +4666,7 @@ export class ConversationModel extends window.Backbone
|
||||||
return lastProfile.profileKeyVersion;
|
return lastProfile.profileKeyVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
const profileKeyVersion = deriveProfileKeyVersion(profileKey, uuid);
|
const profileKeyVersion = deriveProfileKeyVersion(profileKey, serviceId);
|
||||||
if (!profileKeyVersion) {
|
if (!profileKeyVersion) {
|
||||||
log.warn(
|
log.warn(
|
||||||
'deriveProfileKeyVersion: Failed to derive profile key version, ' +
|
'deriveProfileKeyVersion: Failed to derive profile key version, ' +
|
||||||
|
@ -4733,7 +4736,7 @@ export class ConversationModel extends window.Backbone
|
||||||
hasMember(serviceId: ServiceIdString): boolean {
|
hasMember(serviceId: ServiceIdString): boolean {
|
||||||
const members = this.getMembers();
|
const members = this.getMembers();
|
||||||
|
|
||||||
return members.some(member => member.get('uuid') === serviceId);
|
return members.some(member => member.getServiceId() === serviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchContacts(): void {
|
fetchContacts(): void {
|
||||||
|
@ -4818,7 +4821,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set of items to captureChanges on:
|
// Set of items to captureChanges on:
|
||||||
// [-] uuid
|
// [-] serviceId
|
||||||
// [-] e164
|
// [-] e164
|
||||||
// [X] profileKey
|
// [X] profileKey
|
||||||
// [-] identityKey
|
// [-] identityKey
|
||||||
|
@ -4912,14 +4915,14 @@ export class ConversationModel extends window.Backbone
|
||||||
|
|
||||||
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
const ourAci = window.textsecure.storage.user.getCheckedAci();
|
||||||
const ourPni = window.textsecure.storage.user.getCheckedPni();
|
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 => {
|
const mentionsMe = (message.get('bodyRanges') || []).some(bodyRange => {
|
||||||
if (!BodyRange.isMention(bodyRange)) {
|
if (!BodyRange.isMention(bodyRange)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ourUuids.has(
|
return ourServiceIds.has(
|
||||||
normalizeServiceId(bodyRange.mentionUuid, 'notify: mentionsMe check')
|
normalizeServiceId(bodyRange.mentionAci, 'notify: mentionsMe check')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
if (!mentionsMe) {
|
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`,
|
* 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.
|
* than just their id.
|
||||||
*/
|
*/
|
||||||
initialize() {
|
initialize() {
|
||||||
|
@ -5294,8 +5297,8 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
if (idProp === 'e164') {
|
if (idProp === 'e164') {
|
||||||
delete this._byE164[oldValue];
|
delete this._byE164[oldValue];
|
||||||
}
|
}
|
||||||
if (idProp === 'uuid') {
|
if (idProp === 'serviceId') {
|
||||||
delete this._byUuid[oldValue];
|
delete this._byServiceId[oldValue];
|
||||||
}
|
}
|
||||||
if (idProp === 'pni') {
|
if (idProp === 'pni') {
|
||||||
delete this._byPni[oldValue];
|
delete this._byPni[oldValue];
|
||||||
|
@ -5308,11 +5311,11 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
if (e164) {
|
if (e164) {
|
||||||
this._byE164[e164] = model;
|
this._byE164[e164] = model;
|
||||||
}
|
}
|
||||||
const uuid = model.get('uuid');
|
const serviceId = model.getServiceId();
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
this._byUuid[uuid] = model;
|
this._byServiceId[serviceId] = model;
|
||||||
}
|
}
|
||||||
const pni = model.get('pni');
|
const pni = model.getPni();
|
||||||
if (pni) {
|
if (pni) {
|
||||||
this._byPni[pni] = model;
|
this._byPni[pni] = model;
|
||||||
}
|
}
|
||||||
|
@ -5340,28 +5343,28 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
if (e164) {
|
if (e164) {
|
||||||
const existing = this._byE164[e164];
|
const existing = this._byE164[e164];
|
||||||
|
|
||||||
// Prefer the contact with both e164 and uuid
|
// Prefer the contact with both e164 and serviceId
|
||||||
if (!existing || (existing && !existing.get('uuid'))) {
|
if (!existing || (existing && !existing.getServiceId())) {
|
||||||
this._byE164[e164] = model;
|
this._byE164[e164] = model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uuid = model.get('uuid');
|
const serviceId = model.getServiceId();
|
||||||
if (uuid) {
|
if (serviceId) {
|
||||||
const existing = this._byUuid[uuid];
|
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'))) {
|
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) {
|
if (pni) {
|
||||||
const existing = this._byPni[pni];
|
const existing = this._byPni[pni];
|
||||||
|
|
||||||
// Prefer the contact with both uuid and pni
|
// Prefer the contact with both serviceId and pni
|
||||||
if (!existing || (existing && !existing.get('uuid'))) {
|
if (!existing || (existing && !existing.getServiceId())) {
|
||||||
this._byPni[pni] = model;
|
this._byPni[pni] = model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5375,7 +5378,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
|
|
||||||
eraseLookups() {
|
eraseLookups() {
|
||||||
this._byE164 = Object.create(null);
|
this._byE164 = Object.create(null);
|
||||||
this._byUuid = Object.create(null);
|
this._byServiceId = Object.create(null);
|
||||||
this._byPni = Object.create(null);
|
this._byPni = Object.create(null);
|
||||||
this._byGroupId = 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
|
* 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
|
* `_byGroupId` functions, followed by falling back to the original
|
||||||
* window.Backbone implementation.
|
* window.Backbone implementation.
|
||||||
*/
|
*/
|
||||||
|
@ -5435,7 +5438,7 @@ window.Whisper.ConversationCollection = window.Backbone.Collection.extend({
|
||||||
return (
|
return (
|
||||||
this._byE164[id] ||
|
this._byE164[id] ||
|
||||||
this._byE164[`+${id}`] ||
|
this._byE164[`+${id}`] ||
|
||||||
this._byUuid[id] ||
|
this._byServiceId[id] ||
|
||||||
this._byPni[id] ||
|
this._byPni[id] ||
|
||||||
this._byGroupId[id] ||
|
this._byGroupId[id] ||
|
||||||
window.Backbone.Collection.prototype.get.call(this, 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 { ReactionType } from '../types/Reactions';
|
||||||
import type { ServiceIdString } from '../types/ServiceId';
|
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 reactionUtil from '../reactions/util';
|
||||||
import * as Stickers from '../types/Stickers';
|
import * as Stickers from '../types/Stickers';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
|
@ -133,7 +133,7 @@ import { cleanupMessage, deleteMessageData } from '../util/cleanup';
|
||||||
import {
|
import {
|
||||||
getContact,
|
getContact,
|
||||||
getSource,
|
getSource,
|
||||||
getSourceUuid,
|
getSourceServiceId,
|
||||||
isCustomError,
|
isCustomError,
|
||||||
messageHasPaymentEvent,
|
messageHasPaymentEvent,
|
||||||
isQuoteAMatch,
|
isQuoteAMatch,
|
||||||
|
@ -294,13 +294,13 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
getSenderIdentifier(): string {
|
getSenderIdentifier(): string {
|
||||||
const sentAt = this.get('sent_at');
|
const sentAt = this.get('sent_at');
|
||||||
const source = this.get('source');
|
const source = this.get('source');
|
||||||
const sourceUuid = this.get('sourceUuid');
|
const sourceServiceId = this.get('sourceServiceId');
|
||||||
const sourceDevice = this.get('sourceDevice');
|
const sourceDevice = this.get('sourceDevice');
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const conversation = window.ConversationController.lookupOrCreate({
|
const conversation = window.ConversationController.lookupOrCreate({
|
||||||
e164: source,
|
e164: source,
|
||||||
uuid: sourceUuid,
|
serviceId: sourceServiceId,
|
||||||
reason: 'MessageModel.getSenderIdentifier',
|
reason: 'MessageModel.getSenderIdentifier',
|
||||||
})!;
|
})!;
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
attachment: undefined,
|
attachment: undefined,
|
||||||
// This is ok to do because story replies only show in 1:1 conversations
|
// 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.
|
// 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!
|
// No messageId, referenced story not found!
|
||||||
messageId: '',
|
messageId: '',
|
||||||
},
|
},
|
||||||
|
@ -389,10 +389,12 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
attachment = undefined;
|
attachment = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { sourceServiceId: authorAci } = message;
|
||||||
|
strictAssert(isAciString(authorAci), 'Story message from pni');
|
||||||
this.set({
|
this.set({
|
||||||
storyReplyContext: {
|
storyReplyContext: {
|
||||||
attachment,
|
attachment,
|
||||||
authorUuid: message.sourceUuid,
|
authorAci,
|
||||||
messageId: message.id,
|
messageId: message.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -510,7 +512,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (messageHasPaymentEvent(attributes)) {
|
if (messageHasPaymentEvent(attributes)) {
|
||||||
const sender = findAndFormatContact(attributes.sourceUuid);
|
const sender = findAndFormatContact(attributes.sourceServiceId);
|
||||||
const conversation = findAndFormatContact(attributes.conversationId);
|
const conversation = findAndFormatContact(attributes.conversationId);
|
||||||
return {
|
return {
|
||||||
text: getPaymentEventNotificationText(
|
text: getPaymentEventNotificationText(
|
||||||
|
@ -850,7 +852,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
attributes.type === 'incoming' &&
|
attributes.type === 'incoming' &&
|
||||||
attributes.storyReaction.targetAuthorUuid === ourAci
|
attributes.storyReaction.targetAuthorAci === ourAci
|
||||||
) {
|
) {
|
||||||
return window.i18n('icu:Quote__story-reaction-notification--incoming', {
|
return window.i18n('icu:Quote__story-reaction-notification--incoming', {
|
||||||
emoji: attributes.storyReaction.emoji,
|
emoji: attributes.storyReaction.emoji,
|
||||||
|
@ -990,11 +992,11 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
if (!fromSync) {
|
if (!fromSync) {
|
||||||
const senderE164 = getSource(this.attributes);
|
const senderE164 = getSource(this.attributes);
|
||||||
const senderUuid = getSourceUuid(this.attributes);
|
const senderAci = getSourceServiceId(this.attributes);
|
||||||
const timestamp = this.get('sent_at');
|
const timestamp = this.get('sent_at');
|
||||||
|
|
||||||
if (senderUuid === undefined) {
|
if (senderAci === undefined || !isAciString(senderAci)) {
|
||||||
throw new Error('markViewOnceMessageViewed: senderUuid is undefined');
|
throw new Error('markViewOnceMessageViewed: senderAci is undefined');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.ConversationController.areWePrimaryDevice()) {
|
if (window.ConversationController.areWePrimaryDevice()) {
|
||||||
|
@ -1009,7 +1011,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
viewOnceOpens: [
|
viewOnceOpens: [
|
||||||
{
|
{
|
||||||
senderE164,
|
senderE164,
|
||||||
senderUuid,
|
senderAci,
|
||||||
timestamp,
|
timestamp,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1050,8 +1052,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { authorUuid, author, id: sentAt, referencedMessageNotFound } = quote;
|
const { authorAci, author, id: sentAt, referencedMessageNotFound } = quote;
|
||||||
const contact = window.ConversationController.get(authorUuid || author);
|
const contact = window.ConversationController.get(authorAci || author);
|
||||||
|
|
||||||
// Is the quote really without a reference? Check with our in memory store
|
// Is the quote really without a reference? Check with our in memory store
|
||||||
// first to make sure it's not there.
|
// first to make sure it's not there.
|
||||||
|
@ -1289,12 +1291,15 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
if (!isIncoming(this.attributes)) {
|
if (!isIncoming(this.attributes)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const sourceUuid = this.get('sourceUuid');
|
const sourceServiceId = this.get('sourceServiceId');
|
||||||
if (!sourceUuid) {
|
if (!sourceServiceId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.ConversationController.getOrCreate(sourceUuid, 'private');
|
return window.ConversationController.getOrCreate(
|
||||||
|
sourceServiceId,
|
||||||
|
'private'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async retrySend(): Promise<void> {
|
async retrySend(): Promise<void> {
|
||||||
|
@ -1318,7 +1323,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
currentConversationRecipients = new Set(
|
currentConversationRecipients = new Set(
|
||||||
storyDistribution.members
|
storyDistribution.members
|
||||||
.map(uuid => window.ConversationController.get(uuid)?.id)
|
.map(serviceId => window.ConversationController.get(serviceId)?.id)
|
||||||
.filter(isNotNil)
|
.filter(isNotNil)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1947,9 +1952,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
strictAssert(id, 'Quote must have an id');
|
strictAssert(id, 'Quote must have an id');
|
||||||
|
|
||||||
const result: QuotedMessageType = {
|
const result: QuotedMessageType = {
|
||||||
...omit(quote, 'authorAci'),
|
...quote,
|
||||||
|
|
||||||
authorUuid: quote.authorAci,
|
|
||||||
id,
|
id,
|
||||||
|
|
||||||
attachments: quote.attachments.slice(),
|
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
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||||
const message = this;
|
const message = this;
|
||||||
const source = message.get('source');
|
const source = message.get('source');
|
||||||
const sourceUuid = message.get('sourceUuid');
|
const sourceServiceId = message.get('sourceServiceId');
|
||||||
const type = message.get('type');
|
const type = message.get('type');
|
||||||
const conversationId = message.get('conversationId');
|
const conversationId = message.get('conversationId');
|
||||||
|
|
||||||
|
@ -2210,7 +2214,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
|
|
||||||
const destinationConversation =
|
const destinationConversation =
|
||||||
window.ConversationController.lookupOrCreate({
|
window.ConversationController.lookupOrCreate({
|
||||||
uuid: destinationServiceId,
|
serviceId: destinationServiceId,
|
||||||
e164: destination || undefined,
|
e164: destination || undefined,
|
||||||
reason: `handleDataMessage(${initialMessage.timestamp})`,
|
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
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const sender = window.ConversationController.lookupOrCreate({
|
const sender = window.ConversationController.lookupOrCreate({
|
||||||
e164: source,
|
e164: source,
|
||||||
uuid: sourceUuid,
|
serviceId: sourceServiceId,
|
||||||
reason: 'handleDataMessage',
|
reason: 'handleDataMessage',
|
||||||
})!;
|
})!;
|
||||||
const hasGroupV2Prop = Boolean(initialMessage.groupV2);
|
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.
|
// Drop if from blocked user. Only GroupV2 messages should need to be dropped here.
|
||||||
const isBlocked =
|
const isBlocked =
|
||||||
(source && window.storage.blocked.isBlocked(source)) ||
|
(source && window.storage.blocked.isBlocked(source)) ||
|
||||||
(sourceUuid && window.storage.blocked.isUuidBlocked(sourceUuid));
|
(sourceServiceId &&
|
||||||
|
window.storage.blocked.isServiceIdBlocked(sourceServiceId));
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
log.info(
|
log.info(
|
||||||
`${idLog}: Dropping message from blocked sender. hasGroupV2Prop: ${hasGroupV2Prop}`
|
`${idLog}: Dropping message from blocked sender. hasGroupV2Prop: ${hasGroupV2Prop}`
|
||||||
|
@ -2371,7 +2376,8 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
type === 'incoming' &&
|
type === 'incoming' &&
|
||||||
!isDirectConversation(conversation.attributes) &&
|
!isDirectConversation(conversation.attributes) &&
|
||||||
hasGroupV2Prop &&
|
hasGroupV2Prop &&
|
||||||
(!areWeMember || (sourceUuid && !conversation.hasMember(sourceUuid)))
|
(!areWeMember ||
|
||||||
|
(sourceServiceId && !conversation.hasMember(sourceServiceId)))
|
||||||
) {
|
) {
|
||||||
log.warn(
|
log.warn(
|
||||||
`${idLog}: Received message destined for group, which we or the sender are not a part of. Dropping.`
|
`${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.
|
// The queue can be paused easily.
|
||||||
drop(
|
drop(
|
||||||
window.Whisper.deliveryReceiptQueue.add(() => {
|
window.Whisper.deliveryReceiptQueue.add(() => {
|
||||||
|
strictAssert(
|
||||||
|
isAciString(sourceServiceId),
|
||||||
|
'Incoming message must be from ACI'
|
||||||
|
);
|
||||||
window.Whisper.deliveryReceiptBatcher.add({
|
window.Whisper.deliveryReceiptBatcher.add({
|
||||||
messageId,
|
messageId,
|
||||||
conversationId,
|
conversationId,
|
||||||
senderE164: source,
|
senderE164: source,
|
||||||
senderUuid: sourceUuid,
|
senderAci: sourceServiceId,
|
||||||
timestamp: this.get('sent_at'),
|
timestamp: this.get('sent_at'),
|
||||||
isDirectConversation: isDirectConversation(
|
isDirectConversation: isDirectConversation(
|
||||||
conversation.attributes
|
conversation.attributes
|
||||||
|
@ -2456,7 +2466,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
const sendState = sendStateByConversationId[sender.id];
|
const sendState = sendStateByConversationId[sender.id];
|
||||||
|
|
||||||
const storyQuoteIsFromSelf =
|
const storyQuoteIsFromSelf =
|
||||||
candidateQuote.get('sourceUuid') ===
|
candidateQuote.get('sourceServiceId') ===
|
||||||
window.storage.user.getCheckedAci();
|
window.storage.user.getCheckedAci();
|
||||||
|
|
||||||
if (!storyQuoteIsFromSelf) {
|
if (!storyQuoteIsFromSelf) {
|
||||||
|
@ -2573,7 +2583,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ourPni = window.textsecure.storage.user.getCheckedPni();
|
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({
|
message.set({
|
||||||
id: messageId,
|
id: messageId,
|
||||||
|
@ -2594,9 +2604,9 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
if (!BodyRange.isMention(bodyRange)) {
|
if (!BodyRange.isMention(bodyRange)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ourUuids.has(
|
return ourServiceIds.has(
|
||||||
normalizeServiceId(
|
normalizeServiceId(
|
||||||
bodyRange.mentionUuid,
|
bodyRange.mentionAci,
|
||||||
'handleDataMessage: mentionsMe check'
|
'handleDataMessage: mentionsMe check'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2675,7 +2685,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
message.set({
|
message.set({
|
||||||
expirationTimerUpdate: {
|
expirationTimerUpdate: {
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
expireTimer: initialMessage.expireTimer,
|
expireTimer: initialMessage.expireTimer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -2697,7 +2707,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
// point and these calls will return early.
|
// point and these calls will return early.
|
||||||
if (dataMessage.expireTimer) {
|
if (dataMessage.expireTimer) {
|
||||||
void conversation.updateExpirationTimer(dataMessage.expireTimer, {
|
void conversation.updateExpirationTimer(dataMessage.expireTimer, {
|
||||||
source: sourceUuid || source,
|
source: sourceServiceId || source,
|
||||||
receivedAt: message.get('received_at'),
|
receivedAt: message.get('received_at'),
|
||||||
receivedAtMS: message.get('received_at_ms'),
|
receivedAtMS: message.get('received_at_ms'),
|
||||||
sentAt: message.get('sent_at'),
|
sentAt: message.get('sent_at'),
|
||||||
|
@ -2710,7 +2720,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
!isEndSession(message.attributes)
|
!isEndSession(message.attributes)
|
||||||
) {
|
) {
|
||||||
void conversation.updateExpirationTimer(undefined, {
|
void conversation.updateExpirationTimer(undefined, {
|
||||||
source: sourceUuid || source,
|
source: sourceServiceId || source,
|
||||||
receivedAt: message.get('received_at'),
|
receivedAt: message.get('received_at'),
|
||||||
receivedAtMS: message.get('received_at_ms'),
|
receivedAtMS: message.get('received_at_ms'),
|
||||||
sentAt: message.get('sent_at'),
|
sentAt: message.get('sent_at'),
|
||||||
|
@ -2723,7 +2733,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
const { profileKey } = initialMessage;
|
const { profileKey } = initialMessage;
|
||||||
if (
|
if (
|
||||||
source === window.textsecure.storage.user.getNumber() ||
|
source === window.textsecure.storage.user.getNumber() ||
|
||||||
sourceUuid === window.textsecure.storage.user.getAci()
|
sourceServiceId === window.textsecure.storage.user.getAci()
|
||||||
) {
|
) {
|
||||||
conversation.set({ profileSharing: true });
|
conversation.set({ profileSharing: true });
|
||||||
} else if (isDirectConversation(conversation.attributes)) {
|
} else if (isDirectConversation(conversation.attributes)) {
|
||||||
|
@ -2731,7 +2741,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
} else {
|
} else {
|
||||||
const local = window.ConversationController.lookupOrCreate({
|
const local = window.ConversationController.lookupOrCreate({
|
||||||
e164: source,
|
e164: source,
|
||||||
uuid: sourceUuid,
|
serviceId: sourceServiceId,
|
||||||
reason: 'handleDataMessage:setProfileKey',
|
reason: 'handleDataMessage:setProfileKey',
|
||||||
});
|
});
|
||||||
void local?.setProfileKey(profileKey);
|
void local?.setProfileKey(profileKey);
|
||||||
|
@ -2952,7 +2962,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
const newReaction: MessageReactionType = {
|
const newReaction: MessageReactionType = {
|
||||||
emoji: reaction.get('remove') ? undefined : reaction.get('emoji'),
|
emoji: reaction.get('remove') ? undefined : reaction.get('emoji'),
|
||||||
fromId: reaction.get('fromId'),
|
fromId: reaction.get('fromId'),
|
||||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||||
targetTimestamp: reaction.get('targetTimestamp'),
|
targetTimestamp: reaction.get('targetTimestamp'),
|
||||||
timestamp: reaction.get('timestamp'),
|
timestamp: reaction.get('timestamp'),
|
||||||
isSentByConversationId: isFromThisDevice
|
isSentByConversationId: isFromThisDevice
|
||||||
|
@ -3001,7 +3011,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
storyId: storyMessage.id,
|
storyId: storyMessage.id,
|
||||||
storyReaction: {
|
storyReaction: {
|
||||||
emoji: reaction.get('emoji'),
|
emoji: reaction.get('emoji'),
|
||||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||||
targetTimestamp: reaction.get('targetTimestamp'),
|
targetTimestamp: reaction.get('targetTimestamp'),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -3097,7 +3107,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
await window.Signal.Data.removeReactionFromConversation({
|
await window.Signal.Data.removeReactionFromConversation({
|
||||||
emoji: reaction.get('emoji'),
|
emoji: reaction.get('emoji'),
|
||||||
fromId: reaction.get('fromId'),
|
fromId: reaction.get('fromId'),
|
||||||
targetAuthorServiceId: reaction.get('targetAuthorUuid'),
|
targetAuthorServiceId: reaction.get('targetAuthorAci'),
|
||||||
targetTimestamp: reaction.get('targetTimestamp'),
|
targetTimestamp: reaction.get('targetTimestamp'),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -3135,7 +3145,7 @@ export class MessageModel extends window.Backbone.Model<MessageAttributesType> {
|
||||||
fromId: reaction.get('fromId'),
|
fromId: reaction.get('fromId'),
|
||||||
messageId: this.id,
|
messageId: this.id,
|
||||||
messageReceivedAt: this.get('received_at'),
|
messageReceivedAt: this.get('received_at'),
|
||||||
targetAuthorUuid: reaction.get('targetAuthorUuid'),
|
targetAuthorAci: reaction.get('targetAuthorAci'),
|
||||||
targetTimestamp: reaction.get('targetTimestamp'),
|
targetTimestamp: reaction.get('targetTimestamp'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Fuse from 'fuse.js';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
|
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
|
import type { ServiceIdString } from '../types/ServiceId';
|
||||||
import { filter, map } from '../util/iterables';
|
import { filter, map } from '../util/iterables';
|
||||||
import { removeDiacritics } from '../util/removeDiacritics';
|
import { removeDiacritics } from '../util/removeDiacritics';
|
||||||
|
|
||||||
|
@ -67,9 +68,13 @@ export class MemberRepository {
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMemberByUuid(uuid?: string): ConversationType | undefined {
|
getMemberByServiceId(
|
||||||
return uuid
|
serviceId?: ServiceIdString
|
||||||
? this.members.find(({ uuid: memberUuid }) => memberUuid === uuid)
|
): ConversationType | undefined {
|
||||||
|
return serviceId
|
||||||
|
? this.members.find(
|
||||||
|
({ serviceId: memberServiceId }) => memberServiceId === serviceId
|
||||||
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,21 +33,21 @@ export class MentionBlot extends Embed {
|
||||||
}
|
}
|
||||||
|
|
||||||
static override value(node: HTMLElement): MentionBlotValue {
|
static override value(node: HTMLElement): MentionBlotValue {
|
||||||
const { uuid, title } = node.dataset;
|
const { aci, title } = node.dataset;
|
||||||
if (uuid === undefined || title === undefined) {
|
if (aci === undefined || title === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to make MentionBlot with uuid: ${uuid}, title: ${title}`
|
`Failed to make MentionBlot with aci: ${aci}, title: ${title}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
uuid: normalizeAci(uuid, 'quill mention blot'),
|
aci: normalizeAci(aci, 'quill mention blot'),
|
||||||
title,
|
title,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static buildSpan(mention: MentionBlotValue, node: HTMLElement): void {
|
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('data-title', mention.title || '');
|
||||||
node.setAttribute('contenteditable', 'false');
|
node.setAttribute('contenteditable', 'false');
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,7 @@ export class MentionCompletion {
|
||||||
{memberResults.map((member, index) => (
|
{memberResults.map((member, index) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
key={member.uuid}
|
key={member.serviceId}
|
||||||
id={`mention-result--${member.name}`}
|
id={`mention-result--${member.name}`}
|
||||||
role="option button"
|
role="option button"
|
||||||
aria-selected={memberResultsIndex === index}
|
aria-selected={memberResultsIndex === index}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import Delta from 'quill-delta';
|
||||||
import type { RefObject } from 'react';
|
import type { RefObject } from 'react';
|
||||||
import type { Matcher, AttributeMap } from 'quill';
|
import type { Matcher, AttributeMap } from 'quill';
|
||||||
|
|
||||||
|
import { assertDev } from '../../util/assert';
|
||||||
|
import { isAciString } from '../../types/ServiceId';
|
||||||
import type { MemberRepository } from '../memberRepository';
|
import type { MemberRepository } from '../memberRepository';
|
||||||
|
|
||||||
export const matchMention: (
|
export const matchMention: (
|
||||||
|
@ -21,12 +23,14 @@ export const matchMention: (
|
||||||
const { id } = node.dataset;
|
const { id } = node.dataset;
|
||||||
const conversation = memberRepository.getMemberById(id);
|
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(
|
return new Delta().insert(
|
||||||
{
|
{
|
||||||
mention: {
|
mention: {
|
||||||
title,
|
title,
|
||||||
uuid: conversation.uuid,
|
aci,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
attributes
|
attributes
|
||||||
|
@ -37,15 +41,20 @@ export const matchMention: (
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.classList.contains('mention-blot')) {
|
if (node.classList.contains('mention-blot')) {
|
||||||
const { uuid } = node.dataset;
|
const { aci } = node.dataset;
|
||||||
const conversation = memberRepository.getMemberByUuid(uuid);
|
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(
|
return new Delta().insert(
|
||||||
{
|
{
|
||||||
mention: {
|
mention: {
|
||||||
title: title || conversation.title,
|
title: title || conversation.title,
|
||||||
uuid: conversation.uuid,
|
aci,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
attributes
|
attributes
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { isNotNil } from '../util/isNotNil';
|
||||||
import type { AciString } from '../types/ServiceId';
|
import type { AciString } from '../types/ServiceId';
|
||||||
|
|
||||||
export type MentionBlotValue = {
|
export type MentionBlotValue = {
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
title: string;
|
title: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ export const getTextAndRangesFromOps = (
|
||||||
if (isInsertMentionOp(op)) {
|
if (isInsertMentionOp(op)) {
|
||||||
startingBodyRanges.push({
|
startingBodyRanges.push({
|
||||||
length: 1, // The length of `\uFFFC`
|
length: 1, // The length of `\uFFFC`
|
||||||
mentionUuid: op.insert.mention.uuid,
|
mentionAci: op.insert.mention.aci,
|
||||||
replacementText: op.insert.mention.title,
|
replacementText: op.insert.mention.title,
|
||||||
start: acc.length,
|
start: acc.length,
|
||||||
});
|
});
|
||||||
|
@ -291,13 +291,13 @@ export const getDeltaToRestartMention = (ops: Array<Op>): Delta => {
|
||||||
|
|
||||||
export const getDeltaToRemoveStaleMentions = (
|
export const getDeltaToRemoveStaleMentions = (
|
||||||
ops: Array<Op>,
|
ops: Array<Op>,
|
||||||
memberUuids: Array<string>
|
memberAcis: Array<AciString>
|
||||||
): Delta => {
|
): Delta => {
|
||||||
const newOps = ops.reduce((memo, op) => {
|
const newOps = ops.reduce((memo, op) => {
|
||||||
if (op.insert) {
|
if (op.insert) {
|
||||||
if (
|
if (
|
||||||
isInsertMentionOp(op) &&
|
isInsertMentionOp(op) &&
|
||||||
!memberUuids.includes(op.insert.mention.uuid)
|
!memberAcis.includes(op.insert.mention.aci)
|
||||||
) {
|
) {
|
||||||
const deleteOp = { delete: 1 };
|
const deleteOp = { delete: 1 };
|
||||||
const textOp = { insert: `@${op.insert.mention.title}` };
|
const textOp = { insert: `@${op.insert.mention.title}` };
|
||||||
|
@ -360,7 +360,7 @@ export const insertMentionOps = (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { start, length, mentionUuid, replacementText } = bodyRange;
|
const { start, length, mentionAci, replacementText } = bodyRange;
|
||||||
|
|
||||||
const op = ops.shift();
|
const op = ops.shift();
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ export const insertMentionOps = (
|
||||||
const right = insert.slice(start + length);
|
const right = insert.slice(start + length);
|
||||||
|
|
||||||
const mention = {
|
const mention = {
|
||||||
uuid: mentionUuid,
|
aci: mentionAci,
|
||||||
title: replacementText,
|
title: replacementText,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { v4 as generateUuid } from 'uuid';
|
||||||
import { ReactionModel } from '../messageModifiers/Reactions';
|
import { ReactionModel } from '../messageModifiers/Reactions';
|
||||||
import { ReactionSource } from './ReactionSource';
|
import { ReactionSource } from './ReactionSource';
|
||||||
import { getMessageById } from '../messages/getMessageById';
|
import { getMessageById } from '../messages/getMessageById';
|
||||||
import { getSourceUuid, isStory } from '../messages/helpers';
|
import { getSourceServiceId, isStory } from '../messages/helpers';
|
||||||
import { strictAssert } from '../util/assert';
|
import { strictAssert } from '../util/assert';
|
||||||
import { isDirectConversation } from '../util/whatTypeOfConversation';
|
import { isDirectConversation } from '../util/whatTypeOfConversation';
|
||||||
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
import { incrementMessageCounter } from '../util/incrementMessageCounter';
|
||||||
|
@ -28,13 +28,13 @@ export async function enqueueReactionForSend({
|
||||||
const message = await getMessageById(messageId);
|
const message = await getMessageById(messageId);
|
||||||
strictAssert(message, 'enqueueReactionForSend: no message found');
|
strictAssert(message, 'enqueueReactionForSend: no message found');
|
||||||
|
|
||||||
const targetAuthorUuid = getSourceUuid(message.attributes);
|
const targetAuthorAci = getSourceServiceId(message.attributes);
|
||||||
strictAssert(
|
strictAssert(
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
`enqueueReactionForSend: message ${message.idForLogging()} had no source UUID`
|
`enqueueReactionForSend: message ${message.idForLogging()} had no source UUID`
|
||||||
);
|
);
|
||||||
strictAssert(
|
strictAssert(
|
||||||
isAciString(targetAuthorUuid),
|
isAciString(targetAuthorAci),
|
||||||
`enqueueReactionForSend: message ${message.idForLogging()} had no source ACI`
|
`enqueueReactionForSend: message ${message.idForLogging()} had no source ACI`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ export async function enqueueReactionForSend({
|
||||||
const isMessageAStory = isStory(message.attributes);
|
const isMessageAStory = isStory(message.attributes);
|
||||||
const targetConversation =
|
const targetConversation =
|
||||||
isMessageAStory && isDirectConversation(messageConversation.attributes)
|
isMessageAStory && isDirectConversation(messageConversation.attributes)
|
||||||
? window.ConversationController.get(targetAuthorUuid)
|
? window.ConversationController.get(targetAuthorAci)
|
||||||
: messageConversation;
|
: messageConversation;
|
||||||
strictAssert(
|
strictAssert(
|
||||||
targetConversation,
|
targetConversation,
|
||||||
|
@ -92,7 +92,7 @@ export async function enqueueReactionForSend({
|
||||||
storyId: message.id,
|
storyId: message.id,
|
||||||
storyReaction: {
|
storyReaction: {
|
||||||
emoji,
|
emoji,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -104,7 +104,7 @@ export async function enqueueReactionForSend({
|
||||||
remove,
|
remove,
|
||||||
source: ReactionSource.FromThisDevice,
|
source: ReactionSource.FromThisDevice,
|
||||||
storyReactionMessage,
|
storyReactionMessage,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
timestamp,
|
timestamp,
|
||||||
});
|
});
|
||||||
|
|
|
@ -136,7 +136,7 @@ export async function routineProfileRefresh({
|
||||||
|
|
||||||
totalCount += 1;
|
totalCount += 1;
|
||||||
try {
|
try {
|
||||||
await getProfileFn(conversation.get('uuid'), conversation.get('e164'));
|
await getProfileFn(conversation.getServiceId(), conversation.get('e164'));
|
||||||
log.info(
|
log.info(
|
||||||
`${logId}: refreshed profile for ${conversation.idForLogging()}`
|
`${logId}: refreshed profile for ${conversation.idForLogging()}`
|
||||||
);
|
);
|
||||||
|
@ -203,7 +203,7 @@ function* getFilteredConversations(
|
||||||
c =>
|
c =>
|
||||||
isDirectConversation(c.attributes) &&
|
isDirectConversation(c.attributes) &&
|
||||||
!c.isUnregisteredAndStale() &&
|
!c.isUnregisteredAndStale() &&
|
||||||
c.get('uuid')
|
c.getServiceId()
|
||||||
);
|
);
|
||||||
const sorted = sortBy(filtered, c => c.get('profileLastFetchedAt') || 0);
|
const sorted = sortBy(filtered, c => c.get('profileLastFetchedAt') || 0);
|
||||||
|
|
||||||
|
|
|
@ -369,9 +369,9 @@ export class CallingClass {
|
||||||
RingRTC.handleGroupCallRingUpdate =
|
RingRTC.handleGroupCallRingUpdate =
|
||||||
this.handleGroupCallRingUpdate.bind(this);
|
this.handleGroupCallRingUpdate.bind(this);
|
||||||
|
|
||||||
this.attemptToGiveOurUuidToRingRtc();
|
this.attemptToGiveOurServiceIdToRingRtc();
|
||||||
window.Whisper.events.on('userChanged', () => {
|
window.Whisper.events.on('userChanged', () => {
|
||||||
this.attemptToGiveOurUuidToRingRtc();
|
this.attemptToGiveOurServiceIdToRingRtc();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.on('stop-screen-share', () => {
|
ipcRenderer.on('stop-screen-share', () => {
|
||||||
|
@ -381,7 +381,7 @@ export class CallingClass {
|
||||||
void this.cleanExpiredGroupCallRingsAndLoop();
|
void this.cleanExpiredGroupCallRingsAndLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private attemptToGiveOurUuidToRingRtc(): void {
|
private attemptToGiveOurServiceIdToRingRtc(): void {
|
||||||
const ourAci = window.textsecure.storage.user.getAci();
|
const ourAci = window.textsecure.storage.user.getAci();
|
||||||
if (!ourAci) {
|
if (!ourAci) {
|
||||||
// This can happen if we're not linked. It's okay if we hit this case.
|
// 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(
|
return getMembershipList(conversationId).map(
|
||||||
member =>
|
member =>
|
||||||
new GroupMemberInfo(
|
new GroupMemberInfo(
|
||||||
Buffer.from(uuidToBytes(member.uuid)),
|
Buffer.from(uuidToBytes(member.aci)),
|
||||||
Buffer.from(member.uuidCiphertext)
|
Buffer.from(member.uuidCiphertext)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import PQueue from 'p-queue';
|
||||||
|
|
||||||
import type { ContactSyncEvent } from '../textsecure/messageReceiverEvents';
|
import type { ContactSyncEvent } from '../textsecure/messageReceiverEvents';
|
||||||
import type { ModifiedContactDetails } from '../textsecure/ContactsParser';
|
import type { ModifiedContactDetails } from '../textsecure/ContactsParser';
|
||||||
import { normalizeServiceId } from '../types/ServiceId';
|
import { normalizeAci } from '../types/ServiceId';
|
||||||
import * as Conversation from '../types/Conversation';
|
import * as Conversation from '../types/Conversation';
|
||||||
import * as Errors from '../types/errors';
|
import * as Errors from '../types/errors';
|
||||||
import type { ValidateConversationType } from '../model-types.d';
|
import type { ValidateConversationType } from '../model-types.d';
|
||||||
|
@ -91,7 +91,7 @@ async function doContactSync({
|
||||||
for (const details of contacts) {
|
for (const details of contacts) {
|
||||||
const partialConversation: ValidateConversationType = {
|
const partialConversation: ValidateConversationType = {
|
||||||
e164: details.number,
|
e164: details.number,
|
||||||
uuid: normalizeServiceId(details.aci, 'doContactSync'),
|
serviceId: normalizeAci(details.aci, 'doContactSync'),
|
||||||
type: 'private',
|
type: 'private',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ async function doContactSync({
|
||||||
|
|
||||||
const { conversation } = window.ConversationController.maybeMergeContacts({
|
const { conversation } = window.ConversationController.maybeMergeContacts({
|
||||||
e164: details.number,
|
e164: details.number,
|
||||||
aci: details.aci,
|
aci: normalizeAci(details.aci, 'contactSync.aci'),
|
||||||
reason: logId,
|
reason: logId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import * as durations from '../util/durations';
|
||||||
import { BackOff } from '../util/BackOff';
|
import { BackOff } from '../util/BackOff';
|
||||||
import { sleep } from '../util/sleep';
|
import { sleep } from '../util/sleep';
|
||||||
import { toDayMillis } from '../util/timestamp';
|
import { toDayMillis } from '../util/timestamp';
|
||||||
|
import { toAciObject, toPniObject, toTaggedPni } from '../types/ServiceId';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
|
||||||
export const GROUP_CREDENTIALS_KEY = 'groupCredentials';
|
export const GROUP_CREDENTIALS_KEY = 'groupCredentials';
|
||||||
|
@ -150,10 +151,15 @@ export async function maybeFetchNewCredentials(): Promise<void> {
|
||||||
serverPublicParamsBase64
|
serverPublicParamsBase64
|
||||||
);
|
);
|
||||||
|
|
||||||
const { pni, credentials: rawCredentials } = await server.getGroupCredentials(
|
// Received credentials depend on us knowing up-to-date PNI. Use the latest
|
||||||
{ startDayInMs, endDayInMs }
|
// 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();
|
const localPni = window.storage.user.getPni();
|
||||||
if (pni !== localPni) {
|
if (pni !== localPni) {
|
||||||
|
@ -163,9 +169,9 @@ export async function maybeFetchNewCredentials(): Promise<void> {
|
||||||
const newCredentials = sortCredentials(rawCredentials).map(
|
const newCredentials = sortCredentials(rawCredentials).map(
|
||||||
(item: GroupCredentialType) => {
|
(item: GroupCredentialType) => {
|
||||||
const authCredential =
|
const authCredential =
|
||||||
clientZKAuthOperations.receiveAuthCredentialWithPni(
|
clientZKAuthOperations.receiveAuthCredentialWithPniAsServiceId(
|
||||||
aci,
|
toAciObject(aci),
|
||||||
pni,
|
toPniObject(pni),
|
||||||
item.redemptionTime,
|
item.redemptionTime,
|
||||||
new AuthCredentialWithPniResponse(
|
new AuthCredentialWithPniResponse(
|
||||||
Buffer.from(item.credential, 'base64')
|
Buffer.from(item.credential, 'base64')
|
||||||
|
|
|
@ -23,7 +23,7 @@ type NotificationDataType = Readonly<{
|
||||||
notificationIconAbsolutePath?: undefined | string;
|
notificationIconAbsolutePath?: undefined | string;
|
||||||
reaction?: {
|
reaction?: {
|
||||||
emoji: string;
|
emoji: string;
|
||||||
targetAuthorUuid: string;
|
targetAuthorAci: string;
|
||||||
targetTimestamp: number;
|
targetTimestamp: number;
|
||||||
};
|
};
|
||||||
senderTitle: string;
|
senderTitle: string;
|
||||||
|
@ -240,18 +240,18 @@ class NotificationService extends EventEmitter {
|
||||||
// Remove the last notification if both conditions hold:
|
// Remove the last notification if both conditions hold:
|
||||||
//
|
//
|
||||||
// 1. Either `conversationId` or `messageId` matches (if present)
|
// 1. Either `conversationId` or `messageId` matches (if present)
|
||||||
// 2. `emoji`, `targetAuthorUuid`, `targetTimestamp` matches (if present)
|
// 2. `emoji`, `targetAuthorAci`, `targetTimestamp` matches (if present)
|
||||||
public removeBy({
|
public removeBy({
|
||||||
conversationId,
|
conversationId,
|
||||||
messageId,
|
messageId,
|
||||||
emoji,
|
emoji,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
emoji?: string;
|
emoji?: string;
|
||||||
targetAuthorUuid?: string;
|
targetAuthorAci?: string;
|
||||||
targetTimestamp?: number;
|
targetTimestamp?: number;
|
||||||
}>): void {
|
}>): void {
|
||||||
if (!this.notificationData) {
|
if (!this.notificationData) {
|
||||||
|
@ -280,10 +280,10 @@ class NotificationService extends EventEmitter {
|
||||||
if (
|
if (
|
||||||
reaction &&
|
reaction &&
|
||||||
emoji &&
|
emoji &&
|
||||||
targetAuthorUuid &&
|
targetAuthorAci &&
|
||||||
targetTimestamp &&
|
targetTimestamp &&
|
||||||
(reaction.emoji !== emoji ||
|
(reaction.emoji !== emoji ||
|
||||||
reaction.targetAuthorUuid !== targetAuthorUuid ||
|
reaction.targetAuthorAci !== targetAuthorAci ||
|
||||||
reaction.targetTimestamp !== targetTimestamp)
|
reaction.targetTimestamp !== targetTimestamp)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -81,7 +81,7 @@ export class ProfileService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.ConversationController.isSignalConversation(conversationId)) {
|
if (window.ConversationController.isSignalConversationId(conversationId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ async function generateManifest(
|
||||||
identifierType = ITEM_TYPE.ACCOUNT;
|
identifierType = ITEM_TYPE.ACCOUNT;
|
||||||
} else if (conversationType === ConversationTypes.Direct) {
|
} else if (conversationType === ConversationTypes.Direct) {
|
||||||
// Contacts must have UUID
|
// Contacts must have UUID
|
||||||
if (!conversation.get('uuid')) {
|
if (!conversation.getServiceId()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -335,7 +335,7 @@ export function toAccountRecord(
|
||||||
if (pinnedConversation.get('type') === 'private') {
|
if (pinnedConversation.get('type') === 'private') {
|
||||||
pinnedConversationRecord.identifier = 'contact';
|
pinnedConversationRecord.identifier = 'contact';
|
||||||
pinnedConversationRecord.contact = {
|
pinnedConversationRecord.contact = {
|
||||||
uuid: pinnedConversation.get('uuid'),
|
serviceId: pinnedConversation.getServiceId(),
|
||||||
e164: pinnedConversation.get('e164'),
|
e164: pinnedConversation.get('e164'),
|
||||||
};
|
};
|
||||||
} else if (isGroupV1(pinnedConversation.attributes)) {
|
} 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
|
// 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(
|
log.warn(
|
||||||
`mergeContactRecord: ${conversation.idForLogging()} ` +
|
`mergeContactRecord: ${conversation.idForLogging()} ` +
|
||||||
`with storageId ${conversation.get('storageID')} ` +
|
`with storageId ${conversation.get('storageID')} ` +
|
||||||
|
@ -1319,14 +1319,19 @@ export async function mergeAccountRecord(
|
||||||
let conversation: ConversationModel | undefined;
|
let conversation: ConversationModel | undefined;
|
||||||
|
|
||||||
if (contact) {
|
if (contact) {
|
||||||
if (!contact.uuid && !contact.e164) {
|
if (!contact.serviceId && !contact.e164) {
|
||||||
log.error(
|
log.error(
|
||||||
'storageService.mergeAccountRecord: No uuid or e164 on contact'
|
'storageService.mergeAccountRecord: No serviceId or e164 on contact'
|
||||||
);
|
);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
conversation = window.ConversationController.lookupOrCreate({
|
conversation = window.ConversationController.lookupOrCreate({
|
||||||
uuid: contact.uuid,
|
serviceId: contact.serviceId
|
||||||
|
? normalizeServiceId(
|
||||||
|
contact.serviceId,
|
||||||
|
'AccountRecord.pin.serviceId'
|
||||||
|
)
|
||||||
|
: undefined,
|
||||||
e164: contact.e164,
|
e164: contact.e164,
|
||||||
reason: 'storageService.mergeAccountRecord',
|
reason: 'storageService.mergeAccountRecord',
|
||||||
});
|
});
|
||||||
|
@ -1616,13 +1621,13 @@ export async function mergeStoryDistributionListRecord(
|
||||||
|
|
||||||
const localMembersListSet = new Set(localStoryDistributionList.members);
|
const localMembersListSet = new Set(localStoryDistributionList.members);
|
||||||
const toAdd: Array<ServiceIdString> = remoteListMembers.filter(
|
const toAdd: Array<ServiceIdString> = remoteListMembers.filter(
|
||||||
uuid => !localMembersListSet.has(uuid)
|
serviceId => !localMembersListSet.has(serviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
const remoteMemberListSet = new Set(remoteListMembers);
|
const remoteMemberListSet = new Set(remoteListMembers);
|
||||||
const toRemove: Array<ServiceIdString> =
|
const toRemove: Array<ServiceIdString> =
|
||||||
localStoryDistributionList.members.filter(
|
localStoryDistributionList.members.filter(
|
||||||
uuid => !remoteMemberListSet.has(uuid)
|
serviceId => !remoteMemberListSet.has(serviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
details.push('updated');
|
details.push('updated');
|
||||||
|
|
|
@ -112,7 +112,7 @@ export function getStoryDataFromMessageAttributes(
|
||||||
'readStatus',
|
'readStatus',
|
||||||
'sendStateByConversationId',
|
'sendStateByConversationId',
|
||||||
'source',
|
'source',
|
||||||
'sourceUuid',
|
'sourceServiceId',
|
||||||
'storyDistributionListId',
|
'storyDistributionListId',
|
||||||
'storyRecipientsVersion',
|
'storyRecipientsVersion',
|
||||||
'timestamp',
|
'timestamp',
|
||||||
|
@ -144,7 +144,7 @@ async function repairUnexpiredStories(): Promise<void> {
|
||||||
const storiesWithExpiry = storyData
|
const storiesWithExpiry = storyData
|
||||||
.filter(
|
.filter(
|
||||||
story =>
|
story =>
|
||||||
story.sourceUuid !== SIGNAL_ACI &&
|
story.sourceServiceId !== SIGNAL_ACI &&
|
||||||
(!story.expirationStartTimestamp ||
|
(!story.expirationStartTimestamp ||
|
||||||
!story.expireTimer ||
|
!story.expireTimer ||
|
||||||
story.expireTimer > DAY_AS_SECONDS)
|
story.expireTimer > DAY_AS_SECONDS)
|
||||||
|
|
|
@ -29,7 +29,7 @@ export async function writeProfile(
|
||||||
if (!model) {
|
if (!model) {
|
||||||
return;
|
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
|
// Encrypt the profile data, update profile, and if needed upload the avatar
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { assertDev, softAssert } from '../util/assert';
|
||||||
import { mapObjectWithSpec } from '../util/mapObjectWithSpec';
|
import { mapObjectWithSpec } from '../util/mapObjectWithSpec';
|
||||||
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
|
import type { ObjectMappingSpecType } from '../util/mapObjectWithSpec';
|
||||||
import { cleanDataForIpc } from './cleanDataForIpc';
|
import { cleanDataForIpc } from './cleanDataForIpc';
|
||||||
import type { AciString } from '../types/ServiceId';
|
import type { AciString, ServiceIdString } from '../types/ServiceId';
|
||||||
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
import createTaskWithTimeout from '../textsecure/TaskWithTimeout';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
import { isValidUuid } from '../util/isValidUuid';
|
import { isValidUuid } from '../util/isValidUuid';
|
||||||
|
@ -514,19 +514,19 @@ function handleSearchMessageJSON(
|
||||||
async function searchMessages({
|
async function searchMessages({
|
||||||
query,
|
query,
|
||||||
options,
|
options,
|
||||||
contactUuidsMatchingQuery,
|
contactServiceIdsMatchingQuery,
|
||||||
conversationId,
|
conversationId,
|
||||||
}: {
|
}: {
|
||||||
query: string;
|
query: string;
|
||||||
options?: { limit?: number };
|
options?: { limit?: number };
|
||||||
contactUuidsMatchingQuery?: Array<string>;
|
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
}): Promise<Array<ClientSearchResultMessageType>> {
|
}): Promise<Array<ClientSearchResultMessageType>> {
|
||||||
const messages = await channels.searchMessages({
|
const messages = await channels.searchMessages({
|
||||||
query,
|
query,
|
||||||
conversationId,
|
conversationId,
|
||||||
options,
|
options,
|
||||||
contactUuidsMatchingQuery,
|
contactServiceIdsMatchingQuery,
|
||||||
});
|
});
|
||||||
|
|
||||||
return handleSearchMessageJSON(messages);
|
return handleSearchMessageJSON(messages);
|
||||||
|
|
|
@ -14,7 +14,7 @@ import type { AttachmentType } from '../types/Attachment';
|
||||||
import type { BytesToStrings } from '../types/Util';
|
import type { BytesToStrings } from '../types/Util';
|
||||||
import type { QualifiedAddressStringType } from '../types/QualifiedAddress';
|
import type { QualifiedAddressStringType } from '../types/QualifiedAddress';
|
||||||
import type { StoryDistributionIdString } from '../types/StoryDistributionId';
|
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 { BadgeType } from '../badges/types';
|
||||||
import type { RemoveAllConfiguration } from '../types/RemoveAllConfiguration';
|
import type { RemoveAllConfiguration } from '../types/RemoveAllConfiguration';
|
||||||
import type { LoggerType } from '../types/Logging';
|
import type { LoggerType } from '../types/Logging';
|
||||||
|
@ -126,7 +126,7 @@ export type KyberPreKeyType = {
|
||||||
isConfirmed: boolean;
|
isConfirmed: boolean;
|
||||||
isLastResort: boolean;
|
isLastResort: boolean;
|
||||||
keyId: number;
|
keyId: number;
|
||||||
ourUuid: ServiceIdString;
|
ourServiceId: ServiceIdString;
|
||||||
};
|
};
|
||||||
export type StoredKyberPreKeyType = KyberPreKeyType & {
|
export type StoredKyberPreKeyType = KyberPreKeyType & {
|
||||||
data: string;
|
data: string;
|
||||||
|
@ -136,7 +136,7 @@ export type PreKeyType = {
|
||||||
|
|
||||||
createdAt: number;
|
createdAt: number;
|
||||||
keyId: number;
|
keyId: number;
|
||||||
ourUuid: ServiceIdString;
|
ourServiceId: ServiceIdString;
|
||||||
privateKey: Uint8Array;
|
privateKey: Uint8Array;
|
||||||
publicKey: Uint8Array;
|
publicKey: Uint8Array;
|
||||||
};
|
};
|
||||||
|
@ -152,7 +152,7 @@ export type ServerSearchResultMessageType = {
|
||||||
ftsSnippet: string | null;
|
ftsSnippet: string | null;
|
||||||
|
|
||||||
// Otherwise, a matching mention will be returned
|
// Otherwise, a matching mention will be returned
|
||||||
mentionUuid: string | null;
|
mentionAci: string | null;
|
||||||
mentionStart: number | null;
|
mentionStart: number | null;
|
||||||
mentionLength: number | null;
|
mentionLength: number | null;
|
||||||
};
|
};
|
||||||
|
@ -178,7 +178,7 @@ export type SentMessagesType = Array<string>;
|
||||||
// These two are for test only
|
// These two are for test only
|
||||||
export type SentRecipientsDBType = {
|
export type SentRecipientsDBType = {
|
||||||
payloadId: number;
|
payloadId: number;
|
||||||
recipientUuid: string;
|
recipientServiceId: ServiceIdString;
|
||||||
deviceId: number;
|
deviceId: number;
|
||||||
};
|
};
|
||||||
export type SentMessageDBType = {
|
export type SentMessageDBType = {
|
||||||
|
@ -199,8 +199,8 @@ export type SenderKeyType = {
|
||||||
export type SenderKeyIdType = SenderKeyType['id'];
|
export type SenderKeyIdType = SenderKeyType['id'];
|
||||||
export type SessionType = {
|
export type SessionType = {
|
||||||
id: QualifiedAddressStringType;
|
id: QualifiedAddressStringType;
|
||||||
ourUuid: ServiceIdString;
|
ourServiceId: ServiceIdString;
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
deviceId: number;
|
deviceId: number;
|
||||||
record: string;
|
record: string;
|
||||||
|
@ -210,7 +210,7 @@ export type SessionIdType = SessionType['id'];
|
||||||
export type SignedPreKeyType = {
|
export type SignedPreKeyType = {
|
||||||
confirmed: boolean;
|
confirmed: boolean;
|
||||||
created_at: number;
|
created_at: number;
|
||||||
ourUuid: ServiceIdString;
|
ourServiceId: ServiceIdString;
|
||||||
id: `${ServiceIdString}:${number}`;
|
id: `${ServiceIdString}:${number}`;
|
||||||
keyId: number;
|
keyId: number;
|
||||||
privateKey: Uint8Array;
|
privateKey: Uint8Array;
|
||||||
|
@ -219,7 +219,7 @@ export type SignedPreKeyType = {
|
||||||
export type StoredSignedPreKeyType = {
|
export type StoredSignedPreKeyType = {
|
||||||
confirmed: boolean;
|
confirmed: boolean;
|
||||||
created_at: number;
|
created_at: number;
|
||||||
ourUuid: ServiceIdString;
|
ourServiceId: ServiceIdString;
|
||||||
id: `${ServiceIdString}:${number}`;
|
id: `${ServiceIdString}:${number}`;
|
||||||
keyId: number;
|
keyId: number;
|
||||||
privateKey: string;
|
privateKey: string;
|
||||||
|
@ -305,10 +305,10 @@ export type UnprocessedType = {
|
||||||
|
|
||||||
messageAgeSec?: number;
|
messageAgeSec?: number;
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
sourceDevice?: number;
|
sourceDevice?: number;
|
||||||
destinationUuid?: ServiceIdString;
|
destinationServiceId?: ServiceIdString;
|
||||||
updatedPni?: ServiceIdString;
|
updatedPni?: PniString;
|
||||||
serverGuid?: string;
|
serverGuid?: string;
|
||||||
serverTimestamp?: number;
|
serverTimestamp?: number;
|
||||||
decrypted?: string;
|
decrypted?: string;
|
||||||
|
@ -319,7 +319,7 @@ export type UnprocessedType = {
|
||||||
|
|
||||||
export type UnprocessedUpdateType = {
|
export type UnprocessedUpdateType = {
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
sourceDevice?: number;
|
sourceDevice?: number;
|
||||||
serverGuid?: string;
|
serverGuid?: string;
|
||||||
serverTimestamp?: number;
|
serverTimestamp?: number;
|
||||||
|
@ -339,7 +339,7 @@ export type DeleteSentProtoRecipientOptionsType = Readonly<{
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type DeleteSentProtoRecipientResultType = Readonly<{
|
export type DeleteSentProtoRecipientResultType = Readonly<{
|
||||||
successfulPhoneNumberShares: ReadonlyArray<string>;
|
successfulPhoneNumberShares: ReadonlyArray<ServiceIdString>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type StoryDistributionType = Readonly<{
|
export type StoryDistributionType = Readonly<{
|
||||||
|
@ -353,7 +353,7 @@ export type StoryDistributionType = Readonly<{
|
||||||
StorageServiceFieldsType;
|
StorageServiceFieldsType;
|
||||||
export type StoryDistributionMemberType = Readonly<{
|
export type StoryDistributionMemberType = Readonly<{
|
||||||
listId: StoryDistributionIdString;
|
listId: StoryDistributionIdString;
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
}>;
|
}>;
|
||||||
export type StoryDistributionWithMembersType = Readonly<
|
export type StoryDistributionWithMembersType = Readonly<
|
||||||
{
|
{
|
||||||
|
@ -370,7 +370,7 @@ export type StoryReadType = Readonly<{
|
||||||
|
|
||||||
export type ReactionResultType = Pick<
|
export type ReactionResultType = Pick<
|
||||||
ReactionType,
|
ReactionType,
|
||||||
'targetAuthorUuid' | 'targetTimestamp' | 'messageId'
|
'targetAuthorAci' | 'targetTimestamp' | 'messageId'
|
||||||
> & { rowid: number };
|
> & { rowid: number };
|
||||||
|
|
||||||
export type GetUnreadByConversationAndMarkReadResultType = Array<
|
export type GetUnreadByConversationAndMarkReadResultType = Array<
|
||||||
|
@ -378,7 +378,7 @@ export type GetUnreadByConversationAndMarkReadResultType = Array<
|
||||||
MessageType,
|
MessageType,
|
||||||
| 'id'
|
| 'id'
|
||||||
| 'source'
|
| 'source'
|
||||||
| 'sourceUuid'
|
| 'sourceServiceId'
|
||||||
| 'sent_at'
|
| 'sent_at'
|
||||||
| 'type'
|
| 'type'
|
||||||
| 'readStatus'
|
| 'readStatus'
|
||||||
|
@ -593,7 +593,7 @@ export type DataInterface = {
|
||||||
_removeAllReactions: () => Promise<void>;
|
_removeAllReactions: () => Promise<void>;
|
||||||
getMessageBySender: (options: {
|
getMessageBySender: (options: {
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
sourceDevice?: number;
|
sourceDevice?: number;
|
||||||
sent_at: number;
|
sent_at: number;
|
||||||
}) => Promise<MessageType | undefined>;
|
}) => Promise<MessageType | undefined>;
|
||||||
|
@ -618,7 +618,7 @@ export type DataInterface = {
|
||||||
// getOlderMessagesByConversation is JSON on server, full message on Client
|
// getOlderMessagesByConversation is JSON on server, full message on Client
|
||||||
getAllStories: (options: {
|
getAllStories: (options: {
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
}) => Promise<GetAllStoriesResultType>;
|
}) => Promise<GetAllStoriesResultType>;
|
||||||
// getNewerMessagesByConversation is JSON on server, full message on Client
|
// getNewerMessagesByConversation is JSON on server, full message on Client
|
||||||
getMessageMetricsForConversation: (options: {
|
getMessageMetricsForConversation: (options: {
|
||||||
|
@ -838,12 +838,12 @@ export type ServerInterface = DataInterface & {
|
||||||
query,
|
query,
|
||||||
conversationId,
|
conversationId,
|
||||||
options,
|
options,
|
||||||
contactUuidsMatchingQuery,
|
contactServiceIdsMatchingQuery,
|
||||||
}: {
|
}: {
|
||||||
query: string;
|
query: string;
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
options?: { limit?: number };
|
options?: { limit?: number };
|
||||||
contactUuidsMatchingQuery?: Array<string>;
|
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||||
}) => Promise<Array<ServerSearchResultMessageType>>;
|
}) => Promise<Array<ServerSearchResultMessageType>>;
|
||||||
|
|
||||||
getRecentStoryReplies(
|
getRecentStoryReplies(
|
||||||
|
@ -938,12 +938,12 @@ export type ClientExclusiveInterface = {
|
||||||
query,
|
query,
|
||||||
conversationId,
|
conversationId,
|
||||||
options,
|
options,
|
||||||
contactUuidsMatchingQuery,
|
contactServiceIdsMatchingQuery,
|
||||||
}: {
|
}: {
|
||||||
query: string;
|
query: string;
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
options?: { limit?: number };
|
options?: { limit?: number };
|
||||||
contactUuidsMatchingQuery?: Array<string>;
|
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||||
}) => Promise<Array<ClientSearchResultMessageType>>;
|
}) => Promise<Array<ClientSearchResultMessageType>>;
|
||||||
|
|
||||||
getRecentStoryReplies(
|
getRecentStoryReplies(
|
||||||
|
|
218
ts/sql/Server.ts
218
ts/sql/Server.ts
|
@ -716,8 +716,10 @@ async function removeKyberPreKeysByServiceId(
|
||||||
serviceId: ServiceIdString
|
serviceId: ServiceIdString
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
db.prepare<Query>('DELETE FROM kyberPreKeys WHERE ourUuid IS $uuid;').run({
|
db.prepare<Query>(
|
||||||
uuid: serviceId,
|
'DELETE FROM kyberPreKeys WHERE ourServiceId IS $serviceId;'
|
||||||
|
).run({
|
||||||
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function removeAllKyberPreKeys(): Promise<void> {
|
async function removeAllKyberPreKeys(): Promise<void> {
|
||||||
|
@ -748,8 +750,10 @@ async function removePreKeysByServiceId(
|
||||||
serviceId: ServiceIdString
|
serviceId: ServiceIdString
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
db.prepare<Query>('DELETE FROM preKeys WHERE ourUuid IS $uuid;').run({
|
db.prepare<Query>(
|
||||||
uuid: serviceId,
|
'DELETE FROM preKeys WHERE ourServiceId IS $serviceId;'
|
||||||
|
).run({
|
||||||
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function removeAllPreKeys(): Promise<void> {
|
async function removeAllPreKeys(): Promise<void> {
|
||||||
|
@ -784,8 +788,10 @@ async function removeSignedPreKeysByServiceId(
|
||||||
serviceId: ServiceIdString
|
serviceId: ServiceIdString
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
db.prepare<Query>('DELETE FROM signedPreKeys WHERE ourUuid IS $uuid;').run({
|
db.prepare<Query>(
|
||||||
uuid: serviceId,
|
'DELETE FROM signedPreKeys WHERE ourServiceId IS $serviceId;'
|
||||||
|
).run({
|
||||||
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function removeAllSignedPreKeys(): Promise<void> {
|
async function removeAllSignedPreKeys(): Promise<void> {
|
||||||
|
@ -942,11 +948,11 @@ async function insertSentProto(
|
||||||
`
|
`
|
||||||
INSERT INTO sendLogRecipients (
|
INSERT INTO sendLogRecipients (
|
||||||
payloadId,
|
payloadId,
|
||||||
recipientUuid,
|
recipientServiceId,
|
||||||
deviceId
|
deviceId
|
||||||
) VALUES (
|
) VALUES (
|
||||||
$id,
|
$id,
|
||||||
$recipientUuid,
|
$recipientServiceId,
|
||||||
$deviceId
|
$deviceId
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
@ -963,7 +969,7 @@ async function insertSentProto(
|
||||||
for (const deviceId of deviceIds) {
|
for (const deviceId of deviceIds) {
|
||||||
recipientStatement.run({
|
recipientStatement.run({
|
||||||
id,
|
id,
|
||||||
recipientUuid: recipientServiceId,
|
recipientServiceId,
|
||||||
deviceId,
|
deviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1043,11 +1049,11 @@ async function insertProtoRecipients({
|
||||||
`
|
`
|
||||||
INSERT INTO sendLogRecipients (
|
INSERT INTO sendLogRecipients (
|
||||||
payloadId,
|
payloadId,
|
||||||
recipientUuid,
|
recipientServiceId,
|
||||||
deviceId
|
deviceId
|
||||||
) VALUES (
|
) VALUES (
|
||||||
$id,
|
$id,
|
||||||
$recipientUuid,
|
$recipientServiceId,
|
||||||
$deviceId
|
$deviceId
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
|
@ -1056,7 +1062,7 @@ async function insertProtoRecipients({
|
||||||
for (const deviceId of deviceIds) {
|
for (const deviceId of deviceIds) {
|
||||||
statement.run({
|
statement.run({
|
||||||
id,
|
id,
|
||||||
recipientUuid: recipientServiceId,
|
recipientServiceId,
|
||||||
deviceId,
|
deviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1076,7 +1082,7 @@ async function deleteSentProtoRecipient(
|
||||||
// returned row.
|
// returned row.
|
||||||
|
|
||||||
return db.transaction(() => {
|
return db.transaction(() => {
|
||||||
const successfulPhoneNumberShares = new Array<string>();
|
const successfulPhoneNumberShares = new Array<ServiceIdString>();
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const { timestamp, recipientServiceId, deviceId } = item;
|
const { timestamp, recipientServiceId, deviceId } = item;
|
||||||
|
@ -1091,10 +1097,10 @@ async function deleteSentProtoRecipient(
|
||||||
ON sendLogRecipients.payloadId = sendLogPayloads.id
|
ON sendLogRecipients.payloadId = sendLogPayloads.id
|
||||||
WHERE
|
WHERE
|
||||||
sendLogPayloads.timestamp = $timestamp AND
|
sendLogPayloads.timestamp = $timestamp AND
|
||||||
sendLogRecipients.recipientUuid = $recipientUuid AND
|
sendLogRecipients.recipientServiceId = $recipientServiceId AND
|
||||||
sendLogRecipients.deviceId = $deviceId;
|
sendLogRecipients.deviceId = $deviceId;
|
||||||
`
|
`
|
||||||
).all({ timestamp, recipientUuid: recipientServiceId, deviceId });
|
).all({ timestamp, recipientServiceId, deviceId });
|
||||||
if (!rows.length) {
|
if (!rows.length) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1114,20 +1120,20 @@ async function deleteSentProtoRecipient(
|
||||||
DELETE FROM sendLogRecipients
|
DELETE FROM sendLogRecipients
|
||||||
WHERE
|
WHERE
|
||||||
payloadId = $id AND
|
payloadId = $id AND
|
||||||
recipientUuid = $recipientUuid AND
|
recipientServiceId = $recipientServiceId AND
|
||||||
deviceId = $deviceId;
|
deviceId = $deviceId;
|
||||||
`
|
`
|
||||||
).run({ id, recipientUuid: recipientServiceId, deviceId });
|
).run({ id, recipientServiceId, deviceId });
|
||||||
|
|
||||||
// 3. See how many more recipient devices there were for this payload.
|
// 3. See how many more recipient devices there were for this payload.
|
||||||
const remainingDevices = prepare(
|
const remainingDevices = prepare(
|
||||||
db,
|
db,
|
||||||
`
|
`
|
||||||
SELECT count(1) FROM sendLogRecipients
|
SELECT count(1) FROM sendLogRecipients
|
||||||
WHERE payloadId = $id AND recipientUuid = $recipientUuid;
|
WHERE payloadId = $id AND recipientServiceId = $recipientServiceId;
|
||||||
`,
|
`,
|
||||||
{ pluck: true }
|
{ pluck: true }
|
||||||
).get({ id, recipientUuid: recipientServiceId });
|
).get({ id, recipientServiceId });
|
||||||
|
|
||||||
// 4. If there are no remaining devices for this recipient and we included
|
// 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.
|
// 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
|
LEFT JOIN sendLogMessageIds ON sendLogMessageIds.payloadId = sendLogPayloads.id
|
||||||
WHERE
|
WHERE
|
||||||
sendLogPayloads.timestamp = $timestamp AND
|
sendLogPayloads.timestamp = $timestamp AND
|
||||||
sendLogRecipients.recipientUuid = $recipientUuid
|
sendLogRecipients.recipientServiceId = $recipientServiceId
|
||||||
GROUP BY sendLogPayloads.id;
|
GROUP BY sendLogPayloads.id;
|
||||||
`
|
`
|
||||||
).get({
|
).get({
|
||||||
timestamp,
|
timestamp,
|
||||||
recipientUuid: recipientServiceId,
|
recipientServiceId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
|
@ -1265,7 +1271,7 @@ async function _getAllSentProtoMessageIds(): Promise<Array<SentMessageDBType>> {
|
||||||
const SESSIONS_TABLE = 'sessions';
|
const SESSIONS_TABLE = 'sessions';
|
||||||
function createOrUpdateSessionSync(data: SessionType): void {
|
function createOrUpdateSessionSync(data: SessionType): void {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
const { id, conversationId, ourUuid, uuid } = data;
|
const { id, conversationId, ourServiceId, serviceId } = data;
|
||||||
if (!id) {
|
if (!id) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'createOrUpdateSession: Provided data did not have a truthy id'
|
'createOrUpdateSession: Provided data did not have a truthy id'
|
||||||
|
@ -1283,22 +1289,22 @@ function createOrUpdateSessionSync(data: SessionType): void {
|
||||||
INSERT OR REPLACE INTO sessions (
|
INSERT OR REPLACE INTO sessions (
|
||||||
id,
|
id,
|
||||||
conversationId,
|
conversationId,
|
||||||
ourUuid,
|
ourServiceId,
|
||||||
uuid,
|
serviceId,
|
||||||
json
|
json
|
||||||
) values (
|
) values (
|
||||||
$id,
|
$id,
|
||||||
$conversationId,
|
$conversationId,
|
||||||
$ourUuid,
|
$ourServiceId,
|
||||||
$uuid,
|
$serviceId,
|
||||||
$json
|
$json
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
).run({
|
).run({
|
||||||
id,
|
id,
|
||||||
conversationId,
|
conversationId,
|
||||||
ourUuid,
|
ourServiceId,
|
||||||
uuid,
|
serviceId,
|
||||||
json: objectToJSON(data),
|
json: objectToJSON(data),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1370,10 +1376,10 @@ async function removeSessionsByServiceId(
|
||||||
db.prepare<Query>(
|
db.prepare<Query>(
|
||||||
`
|
`
|
||||||
DELETE FROM sessions
|
DELETE FROM sessions
|
||||||
WHERE uuid = $uuid;
|
WHERE serviceId = $serviceId;
|
||||||
`
|
`
|
||||||
).run({
|
).run({
|
||||||
uuid: serviceId,
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
async function removeAllSessions(): Promise<void> {
|
async function removeAllSessions(): Promise<void> {
|
||||||
|
@ -1390,7 +1396,7 @@ async function getConversationCount(): Promise<number> {
|
||||||
|
|
||||||
function getConversationMembersList({ members, membersV2 }: ConversationType) {
|
function getConversationMembersList({ members, membersV2 }: ConversationType) {
|
||||||
if (membersV2) {
|
if (membersV2) {
|
||||||
return membersV2.map((item: GroupV2MemberType) => item.uuid).join(' ');
|
return membersV2.map((item: GroupV2MemberType) => item.aci).join(' ');
|
||||||
}
|
}
|
||||||
if (members) {
|
if (members) {
|
||||||
return members.join(' ');
|
return members.join(' ');
|
||||||
|
@ -1412,7 +1418,7 @@ function saveConversationSync(
|
||||||
profileName,
|
profileName,
|
||||||
profileLastFetchedAt,
|
profileLastFetchedAt,
|
||||||
type,
|
type,
|
||||||
uuid,
|
serviceId,
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
const membersList = getConversationMembersList(data);
|
const membersList = getConversationMembersList(data);
|
||||||
|
@ -1424,7 +1430,7 @@ function saveConversationSync(
|
||||||
json,
|
json,
|
||||||
|
|
||||||
e164,
|
e164,
|
||||||
uuid,
|
serviceId,
|
||||||
groupId,
|
groupId,
|
||||||
|
|
||||||
active_at,
|
active_at,
|
||||||
|
@ -1440,7 +1446,7 @@ function saveConversationSync(
|
||||||
$json,
|
$json,
|
||||||
|
|
||||||
$e164,
|
$e164,
|
||||||
$uuid,
|
$serviceId,
|
||||||
$groupId,
|
$groupId,
|
||||||
|
|
||||||
$active_at,
|
$active_at,
|
||||||
|
@ -1460,7 +1466,7 @@ function saveConversationSync(
|
||||||
),
|
),
|
||||||
|
|
||||||
e164: e164 || null,
|
e164: e164 || null,
|
||||||
uuid: uuid || null,
|
serviceId: serviceId || null,
|
||||||
groupId: groupId || null,
|
groupId: groupId || null,
|
||||||
|
|
||||||
active_at: active_at || null,
|
active_at: active_at || null,
|
||||||
|
@ -1506,7 +1512,7 @@ function updateConversationSync(
|
||||||
profileFamilyName,
|
profileFamilyName,
|
||||||
profileLastFetchedAt,
|
profileLastFetchedAt,
|
||||||
e164,
|
e164,
|
||||||
uuid,
|
serviceId,
|
||||||
} = data;
|
} = data;
|
||||||
|
|
||||||
const membersList = getConversationMembersList(data);
|
const membersList = getConversationMembersList(data);
|
||||||
|
@ -1517,7 +1523,7 @@ function updateConversationSync(
|
||||||
json = $json,
|
json = $json,
|
||||||
|
|
||||||
e164 = $e164,
|
e164 = $e164,
|
||||||
uuid = $uuid,
|
serviceId = $serviceId,
|
||||||
|
|
||||||
active_at = $active_at,
|
active_at = $active_at,
|
||||||
type = $type,
|
type = $type,
|
||||||
|
@ -1536,7 +1542,7 @@ function updateConversationSync(
|
||||||
),
|
),
|
||||||
|
|
||||||
e164: e164 || null,
|
e164: e164 || null,
|
||||||
uuid: uuid || null,
|
serviceId: serviceId || null,
|
||||||
|
|
||||||
active_at: active_at || null,
|
active_at: active_at || null,
|
||||||
type,
|
type,
|
||||||
|
@ -1668,12 +1674,12 @@ async function getAllGroupsInvolvingServiceId(
|
||||||
SELECT json, profileLastFetchedAt
|
SELECT json, profileLastFetchedAt
|
||||||
FROM conversations WHERE
|
FROM conversations WHERE
|
||||||
type = 'group' AND
|
type = 'group' AND
|
||||||
members LIKE $uuid
|
members LIKE $serviceId
|
||||||
ORDER BY id ASC;
|
ORDER BY id ASC;
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
.all({
|
.all({
|
||||||
uuid: `%${serviceId}%`,
|
serviceId: `%${serviceId}%`,
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows.map(row => rowToConversation(row));
|
return rows.map(row => rowToConversation(row));
|
||||||
|
@ -1683,12 +1689,12 @@ async function searchMessages({
|
||||||
query,
|
query,
|
||||||
options,
|
options,
|
||||||
conversationId,
|
conversationId,
|
||||||
contactUuidsMatchingQuery,
|
contactServiceIdsMatchingQuery,
|
||||||
}: {
|
}: {
|
||||||
query: string;
|
query: string;
|
||||||
options?: { limit?: number };
|
options?: { limit?: number };
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
contactUuidsMatchingQuery?: Array<string>;
|
contactServiceIdsMatchingQuery?: Array<ServiceIdString>;
|
||||||
}): Promise<Array<ServerSearchResultMessageType>> {
|
}): Promise<Array<ServerSearchResultMessageType>> {
|
||||||
const { limit = conversationId ? 100 : 500 } = options ?? {};
|
const { limit = conversationId ? 100 : 500 } = options ?? {};
|
||||||
|
|
||||||
|
@ -1781,12 +1787,12 @@ async function searchMessages({
|
||||||
|
|
||||||
let result: Array<ServerSearchResultMessageType>;
|
let result: Array<ServerSearchResultMessageType>;
|
||||||
|
|
||||||
if (!contactUuidsMatchingQuery?.length) {
|
if (!contactServiceIdsMatchingQuery?.length) {
|
||||||
const [sqlQuery, params] = sql`${ftsFragment};`;
|
const [sqlQuery, params] = sql`${ftsFragment};`;
|
||||||
result = db.prepare(sqlQuery).all(params);
|
result = db.prepare(sqlQuery).all(params);
|
||||||
} else {
|
} else {
|
||||||
// If contactUuidsMatchingQuery is not empty, we due an OUTER JOIN between:
|
// If contactServiceIdsMatchingQuery is not empty, we due an OUTER JOIN between:
|
||||||
// 1) the messages that mention at least one of contactUuidsMatchingQuery, and
|
// 1) the messages that mention at least one of contactServiceIdsMatchingQuery, and
|
||||||
// 2) the messages that match all the search terms via FTS
|
// 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
|
// 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.sent_at, ftsResults.sent_at) as sent_at,
|
||||||
COALESCE(messages.received_at, ftsResults.received_at) as received_at,
|
COALESCE(messages.received_at, ftsResults.received_at) as received_at,
|
||||||
ftsResults.ftsSnippet,
|
ftsResults.ftsSnippet,
|
||||||
mentionUuid,
|
mentionAci,
|
||||||
start as mentionStart,
|
start as mentionStart,
|
||||||
length as mentionLength
|
length as mentionLength
|
||||||
FROM mentions
|
FROM mentions
|
||||||
INNER JOIN messages
|
INNER JOIN messages
|
||||||
ON
|
ON
|
||||||
messages.id = mentions.messageId
|
messages.id = mentions.messageId
|
||||||
AND mentions.mentionUuid IN (
|
AND mentions.mentionAci IN (
|
||||||
${sqlJoin(contactUuidsMatchingQuery, ', ')}
|
${sqlJoin(contactServiceIdsMatchingQuery, ', ')}
|
||||||
)
|
)
|
||||||
AND ${
|
AND ${
|
||||||
conversationId
|
conversationId
|
||||||
|
@ -1944,7 +1950,7 @@ function saveMessageSync(
|
||||||
sent_at,
|
sent_at,
|
||||||
serverGuid,
|
serverGuid,
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
storyId,
|
storyId,
|
||||||
callId,
|
callId,
|
||||||
|
@ -2002,7 +2008,7 @@ function saveMessageSync(
|
||||||
serverGuid: serverGuid || null,
|
serverGuid: serverGuid || null,
|
||||||
sent_at: sent_at || null,
|
sent_at: sent_at || null,
|
||||||
source: source || null,
|
source: source || null,
|
||||||
sourceUuid: sourceUuid || null,
|
sourceServiceId: sourceServiceId || null,
|
||||||
sourceDevice: sourceDevice || null,
|
sourceDevice: sourceDevice || null,
|
||||||
storyId: storyId || null,
|
storyId: storyId || null,
|
||||||
callId: callId || null,
|
callId: callId || null,
|
||||||
|
@ -2035,7 +2041,7 @@ function saveMessageSync(
|
||||||
serverGuid = $serverGuid,
|
serverGuid = $serverGuid,
|
||||||
sent_at = $sent_at,
|
sent_at = $sent_at,
|
||||||
source = $source,
|
source = $source,
|
||||||
sourceUuid = $sourceUuid,
|
sourceServiceId = $sourceServiceId,
|
||||||
sourceDevice = $sourceDevice,
|
sourceDevice = $sourceDevice,
|
||||||
storyId = $storyId,
|
storyId = $storyId,
|
||||||
callId = $callId,
|
callId = $callId,
|
||||||
|
@ -2081,7 +2087,7 @@ function saveMessageSync(
|
||||||
serverGuid,
|
serverGuid,
|
||||||
sent_at,
|
sent_at,
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
storyId,
|
storyId,
|
||||||
callId,
|
callId,
|
||||||
|
@ -2108,7 +2114,7 @@ function saveMessageSync(
|
||||||
$serverGuid,
|
$serverGuid,
|
||||||
$sent_at,
|
$sent_at,
|
||||||
$source,
|
$source,
|
||||||
$sourceUuid,
|
$sourceServiceId,
|
||||||
$sourceDevice,
|
$sourceDevice,
|
||||||
$storyId,
|
$storyId,
|
||||||
$callId,
|
$callId,
|
||||||
|
@ -2247,12 +2253,12 @@ async function getAllMessageIds(): Promise<Array<string>> {
|
||||||
|
|
||||||
async function getMessageBySender({
|
async function getMessageBySender({
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
sent_at,
|
sent_at,
|
||||||
}: {
|
}: {
|
||||||
source?: string;
|
source?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
sourceDevice?: number;
|
sourceDevice?: number;
|
||||||
sent_at: number;
|
sent_at: number;
|
||||||
}): Promise<MessageType | undefined> {
|
}): Promise<MessageType | undefined> {
|
||||||
|
@ -2261,14 +2267,14 @@ async function getMessageBySender({
|
||||||
db,
|
db,
|
||||||
`
|
`
|
||||||
SELECT json FROM messages WHERE
|
SELECT json FROM messages WHERE
|
||||||
(source = $source OR sourceUuid = $sourceUuid) AND
|
(source = $source OR sourceServiceId = $sourceServiceId) AND
|
||||||
sourceDevice = $sourceDevice AND
|
sourceDevice = $sourceDevice AND
|
||||||
sent_at = $sent_at
|
sent_at = $sent_at
|
||||||
LIMIT 2;
|
LIMIT 2;
|
||||||
`
|
`
|
||||||
).all({
|
).all({
|
||||||
source: source || null,
|
source: source || null,
|
||||||
sourceUuid: sourceUuid || null,
|
sourceServiceId: sourceServiceId || null,
|
||||||
sourceDevice: sourceDevice || null,
|
sourceDevice: sourceDevice || null,
|
||||||
sent_at,
|
sent_at,
|
||||||
});
|
});
|
||||||
|
@ -2277,7 +2283,7 @@ async function getMessageBySender({
|
||||||
log.warn('getMessageBySender: More than one message found for', {
|
log.warn('getMessageBySender: More than one message found for', {
|
||||||
sent_at,
|
sent_at,
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2392,7 +2398,7 @@ async function getUnreadByConversationAndMarkRead({
|
||||||
'id',
|
'id',
|
||||||
'sent_at',
|
'sent_at',
|
||||||
'source',
|
'source',
|
||||||
'sourceUuid',
|
'sourceServiceId',
|
||||||
'type',
|
'type',
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
@ -2415,7 +2421,7 @@ async function getUnreadReactionsAndMarkRead({
|
||||||
const unreadMessages: Array<ReactionResultType> = db
|
const unreadMessages: Array<ReactionResultType> = db
|
||||||
.prepare<Query>(
|
.prepare<Query>(
|
||||||
`
|
`
|
||||||
SELECT reactions.rowid, targetAuthorUuid, targetTimestamp, messageId
|
SELECT reactions.rowid, targetAuthorAci, targetTimestamp, messageId
|
||||||
FROM reactions
|
FROM reactions
|
||||||
INDEXED BY reactions_unread
|
INDEXED BY reactions_unread
|
||||||
JOIN messages on messages.id IS reactions.messageId
|
JOIN messages on messages.id IS reactions.messageId
|
||||||
|
@ -2460,7 +2466,7 @@ async function markReactionAsRead(
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM reactions
|
FROM reactions
|
||||||
WHERE
|
WHERE
|
||||||
targetAuthorUuid = $targetAuthorUuid AND
|
targetAuthorAci = $targetAuthorAci AND
|
||||||
targetTimestamp = $targetTimestamp AND
|
targetTimestamp = $targetTimestamp AND
|
||||||
unread = 1
|
unread = 1
|
||||||
ORDER BY rowId DESC
|
ORDER BY rowId DESC
|
||||||
|
@ -2468,7 +2474,7 @@ async function markReactionAsRead(
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
.get({
|
.get({
|
||||||
targetAuthorUuid: targetAuthorServiceId,
|
targetAuthorAci: targetAuthorServiceId,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2476,11 +2482,11 @@ async function markReactionAsRead(
|
||||||
`
|
`
|
||||||
UPDATE reactions SET
|
UPDATE reactions SET
|
||||||
unread = 0 WHERE
|
unread = 0 WHERE
|
||||||
targetAuthorUuid = $targetAuthorUuid AND
|
targetAuthorAci = $targetAuthorAci AND
|
||||||
targetTimestamp = $targetTimestamp;
|
targetTimestamp = $targetTimestamp;
|
||||||
`
|
`
|
||||||
).run({
|
).run({
|
||||||
targetAuthorUuid: targetAuthorServiceId,
|
targetAuthorAci: targetAuthorServiceId,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2494,7 +2500,7 @@ async function addReaction({
|
||||||
fromId,
|
fromId,
|
||||||
messageId,
|
messageId,
|
||||||
messageReceivedAt,
|
messageReceivedAt,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
}: ReactionType): Promise<void> {
|
}: ReactionType): Promise<void> {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
|
@ -2506,7 +2512,7 @@ async function addReaction({
|
||||||
fromId,
|
fromId,
|
||||||
messageId,
|
messageId,
|
||||||
messageReceivedAt,
|
messageReceivedAt,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
unread
|
unread
|
||||||
) VALUES (
|
) VALUES (
|
||||||
|
@ -2515,7 +2521,7 @@ async function addReaction({
|
||||||
$fromId,
|
$fromId,
|
||||||
$messageId,
|
$messageId,
|
||||||
$messageReceivedAt,
|
$messageReceivedAt,
|
||||||
$targetAuthorUuid,
|
$targetAuthorAci,
|
||||||
$targetTimestamp,
|
$targetTimestamp,
|
||||||
$unread
|
$unread
|
||||||
);`
|
);`
|
||||||
|
@ -2526,7 +2532,7 @@ async function addReaction({
|
||||||
fromId,
|
fromId,
|
||||||
messageId,
|
messageId,
|
||||||
messageReceivedAt,
|
messageReceivedAt,
|
||||||
targetAuthorUuid,
|
targetAuthorAci,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
unread: 1,
|
unread: 1,
|
||||||
});
|
});
|
||||||
|
@ -2549,13 +2555,13 @@ async function removeReactionFromConversation({
|
||||||
`DELETE FROM reactions WHERE
|
`DELETE FROM reactions WHERE
|
||||||
emoji = $emoji AND
|
emoji = $emoji AND
|
||||||
fromId = $fromId AND
|
fromId = $fromId AND
|
||||||
targetAuthorUuid = $targetAuthorUuid AND
|
targetAuthorAci = $targetAuthorAci AND
|
||||||
targetTimestamp = $targetTimestamp;`
|
targetTimestamp = $targetTimestamp;`
|
||||||
)
|
)
|
||||||
.run({
|
.run({
|
||||||
emoji,
|
emoji,
|
||||||
fromId,
|
fromId,
|
||||||
targetAuthorUuid: targetAuthorServiceId,
|
targetAuthorAci: targetAuthorServiceId,
|
||||||
targetTimestamp,
|
targetTimestamp,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2725,10 +2731,10 @@ async function getOlderMessagesByConversation(
|
||||||
|
|
||||||
async function getAllStories({
|
async function getAllStories({
|
||||||
conversationId,
|
conversationId,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
}: {
|
}: {
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
sourceUuid?: ServiceIdString;
|
sourceServiceId?: ServiceIdString;
|
||||||
}): Promise<GetAllStoriesResultType> {
|
}): Promise<GetAllStoriesResultType> {
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
const rows: ReadonlyArray<{
|
const rows: ReadonlyArray<{
|
||||||
|
@ -2756,13 +2762,13 @@ async function getAllStories({
|
||||||
WHERE
|
WHERE
|
||||||
type IS 'story' AND
|
type IS 'story' AND
|
||||||
($conversationId IS NULL OR conversationId IS $conversationId) 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;
|
ORDER BY received_at ASC, sent_at ASC;
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
.all({
|
.all({
|
||||||
conversationId: conversationId || null,
|
conversationId: conversationId || null,
|
||||||
sourceUuid: sourceUuid || null,
|
sourceServiceId: sourceServiceId || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows.map(row => ({
|
return rows.map(row => ({
|
||||||
|
@ -3396,7 +3402,7 @@ function getCallHistoryGroupDataSync(
|
||||||
const [createTempTable] = sql`
|
const [createTempTable] = sql`
|
||||||
CREATE TEMP TABLE temp_callHistory_filtered_conversations (
|
CREATE TEMP TABLE temp_callHistory_filtered_conversations (
|
||||||
id TEXT,
|
id TEXT,
|
||||||
uuid TEXT,
|
serviceId TEXT,
|
||||||
groupId TEXT
|
groupId TEXT
|
||||||
);
|
);
|
||||||
`;
|
`;
|
||||||
|
@ -3411,8 +3417,8 @@ function getCallHistoryGroupDataSync(
|
||||||
|
|
||||||
const [insertQuery, insertParams] = sql`
|
const [insertQuery, insertParams] = sql`
|
||||||
INSERT INTO temp_callHistory_filtered_conversations
|
INSERT INTO temp_callHistory_filtered_conversations
|
||||||
(id, uuid, groupId)
|
(id, serviceId, groupId)
|
||||||
SELECT id, uuid, groupId
|
SELECT id, serviceId, groupId
|
||||||
FROM conversations
|
FROM conversations
|
||||||
WHERE conversations.id IN (${idList});
|
WHERE conversations.id IN (${idList});
|
||||||
`;
|
`;
|
||||||
|
@ -3423,11 +3429,11 @@ function getCallHistoryGroupDataSync(
|
||||||
|
|
||||||
const innerJoin =
|
const innerJoin =
|
||||||
conversationIds != null
|
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`
|
sqlFragment`
|
||||||
INNER JOIN temp_callHistory_filtered_conversations ON (
|
INNER JOIN temp_callHistory_filtered_conversations ON (
|
||||||
temp_callHistory_filtered_conversations.id IS c.peerId
|
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
|
OR temp_callHistory_filtered_conversations.groupId IS c.peerId
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
@ -3849,7 +3855,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
||||||
attempts,
|
attempts,
|
||||||
envelope,
|
envelope,
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
serverGuid,
|
serverGuid,
|
||||||
serverTimestamp,
|
serverTimestamp,
|
||||||
|
@ -3872,7 +3878,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
||||||
attempts,
|
attempts,
|
||||||
envelope,
|
envelope,
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
serverGuid,
|
serverGuid,
|
||||||
serverTimestamp,
|
serverTimestamp,
|
||||||
|
@ -3887,7 +3893,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
||||||
$attempts,
|
$attempts,
|
||||||
$envelope,
|
$envelope,
|
||||||
$source,
|
$source,
|
||||||
$sourceUuid,
|
$sourceServiceId,
|
||||||
$sourceDevice,
|
$sourceDevice,
|
||||||
$serverGuid,
|
$serverGuid,
|
||||||
$serverTimestamp,
|
$serverTimestamp,
|
||||||
|
@ -3904,7 +3910,7 @@ function saveUnprocessedSync(data: UnprocessedType): string {
|
||||||
attempts,
|
attempts,
|
||||||
envelope: envelope || null,
|
envelope: envelope || null,
|
||||||
source: source || null,
|
source: source || null,
|
||||||
sourceUuid: sourceUuid || null,
|
sourceServiceId: sourceServiceId || null,
|
||||||
sourceDevice: sourceDevice || null,
|
sourceDevice: sourceDevice || null,
|
||||||
serverGuid: serverGuid || null,
|
serverGuid: serverGuid || null,
|
||||||
serverTimestamp: serverTimestamp || null,
|
serverTimestamp: serverTimestamp || null,
|
||||||
|
@ -3923,7 +3929,7 @@ function updateUnprocessedWithDataSync(
|
||||||
const db = getInstance();
|
const db = getInstance();
|
||||||
const {
|
const {
|
||||||
source,
|
source,
|
||||||
sourceUuid,
|
sourceServiceId,
|
||||||
sourceDevice,
|
sourceDevice,
|
||||||
serverGuid,
|
serverGuid,
|
||||||
serverTimestamp,
|
serverTimestamp,
|
||||||
|
@ -3935,7 +3941,7 @@ function updateUnprocessedWithDataSync(
|
||||||
`
|
`
|
||||||
UPDATE unprocessed SET
|
UPDATE unprocessed SET
|
||||||
source = $source,
|
source = $source,
|
||||||
sourceUuid = $sourceUuid,
|
sourceServiceId = $sourceServiceId,
|
||||||
sourceDevice = $sourceDevice,
|
sourceDevice = $sourceDevice,
|
||||||
serverGuid = $serverGuid,
|
serverGuid = $serverGuid,
|
||||||
serverTimestamp = $serverTimestamp,
|
serverTimestamp = $serverTimestamp,
|
||||||
|
@ -3945,7 +3951,7 @@ function updateUnprocessedWithDataSync(
|
||||||
).run({
|
).run({
|
||||||
id,
|
id,
|
||||||
source: source || null,
|
source: source || null,
|
||||||
sourceUuid: sourceUuid || null,
|
sourceServiceId: sourceServiceId || null,
|
||||||
sourceDevice: sourceDevice || null,
|
sourceDevice: sourceDevice || null,
|
||||||
serverGuid: serverGuid || null,
|
serverGuid: serverGuid || null,
|
||||||
serverTimestamp: serverTimestamp || null,
|
serverTimestamp: serverTimestamp || null,
|
||||||
|
@ -5238,18 +5244,18 @@ async function createNewStoryDistribution(
|
||||||
`
|
`
|
||||||
INSERT OR REPLACE INTO storyDistributionMembers (
|
INSERT OR REPLACE INTO storyDistributionMembers (
|
||||||
listId,
|
listId,
|
||||||
uuid
|
serviceId
|
||||||
) VALUES (
|
) VALUES (
|
||||||
$listId,
|
$listId,
|
||||||
$uuid
|
$serviceId
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const uuid of members) {
|
for (const serviceId of members) {
|
||||||
memberInsertStatement.run({
|
memberInsertStatement.run({
|
||||||
listId,
|
listId,
|
||||||
uuid,
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -5264,7 +5270,7 @@ async function getAllStoryDistributionsWithMembers(): Promise<
|
||||||
|
|
||||||
return allDistributions.map(list => ({
|
return allDistributions.map(list => ({
|
||||||
...list,
|
...list,
|
||||||
members: (byListId[list.id] || []).map(member => member.uuid),
|
members: (byListId[list.id] || []).map(member => member.serviceId),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
async function getStoryDistributionWithMembers(
|
async function getStoryDistributionWithMembers(
|
||||||
|
@ -5291,7 +5297,7 @@ async function getStoryDistributionWithMembers(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...hydrateStoryDistribution(storyDistribution),
|
...hydrateStoryDistribution(storyDistribution),
|
||||||
members: members.map(({ uuid }) => uuid),
|
members: members.map(({ serviceId }) => serviceId),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function modifyStoryDistributionSync(
|
function modifyStoryDistributionSync(
|
||||||
|
@ -5341,29 +5347,33 @@ function modifyStoryDistributionMembersSync(
|
||||||
`
|
`
|
||||||
INSERT OR REPLACE INTO storyDistributionMembers (
|
INSERT OR REPLACE INTO storyDistributionMembers (
|
||||||
listId,
|
listId,
|
||||||
uuid
|
serviceId
|
||||||
) VALUES (
|
) VALUES (
|
||||||
$listId,
|
$listId,
|
||||||
$uuid
|
$serviceId
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const uuid of toAdd) {
|
for (const serviceId of toAdd) {
|
||||||
memberInsertStatement.run({
|
memberInsertStatement.run({
|
||||||
listId,
|
listId,
|
||||||
uuid,
|
serviceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
batchMultiVarQuery(db, toRemove, (uuids: ReadonlyArray<ServiceIdString>) => {
|
batchMultiVarQuery(
|
||||||
db.prepare<ArrayQuery>(
|
db,
|
||||||
`
|
toRemove,
|
||||||
|
(serviceIds: ReadonlyArray<ServiceIdString>) => {
|
||||||
|
const serviceIdSet = sqlJoin(serviceIds, '?');
|
||||||
|
const [sqlQuery, sqlParams] = sql`
|
||||||
DELETE FROM storyDistributionMembers
|
DELETE FROM storyDistributionMembers
|
||||||
WHERE listId = ? AND uuid IN ( ${uuids.map(() => '?').join(', ')} );
|
WHERE listId = ${listId} AND serviceId IN (${serviceIdSet});
|
||||||
`
|
`;
|
||||||
).run([listId, ...uuids]);
|
db.prepare(sqlQuery).run(sqlParams);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
async function modifyStoryDistributionWithMembers(
|
async function modifyStoryDistributionWithMembers(
|
||||||
distribution: StoryDistributionType,
|
distribution: StoryDistributionType,
|
||||||
|
@ -6372,7 +6382,7 @@ async function getUnreadEditedMessagesAndMarkRead({
|
||||||
'id',
|
'id',
|
||||||
'sent_at',
|
'sent_at',
|
||||||
'source',
|
'source',
|
||||||
'sourceUuid',
|
'sourceServiceId',
|
||||||
'type',
|
'type',
|
||||||
]),
|
]),
|
||||||
// Use the edited message timestamp
|
// Use the edited message timestamp
|
||||||
|
|
|
@ -16,7 +16,22 @@ import {
|
||||||
objectToJSON,
|
objectToJSON,
|
||||||
} from '../util';
|
} from '../util';
|
||||||
import type { EmptyQuery, Query } 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(
|
export default function updateToSchemaVersion43(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
import type { Database } from '@signalapp/better-sqlite3';
|
import type { Database } from '@signalapp/better-sqlite3';
|
||||||
|
|
||||||
import type { LoggerType } from '../../types/Logging';
|
import type { LoggerType } from '../../types/Logging';
|
||||||
import type { ServiceIdString } from '../../types/ServiceId';
|
|
||||||
import { jsonToObject } from '../util';
|
import { jsonToObject } from '../util';
|
||||||
import type { EmptyQuery } from '../util';
|
import type { EmptyQuery } from '../util';
|
||||||
import type { ConversationType } from '../Interface';
|
|
||||||
|
|
||||||
export default function updateToSchemaVersion53(
|
export default function updateToSchemaVersion53(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
|
@ -21,7 +19,13 @@ export default function updateToSchemaVersion53(
|
||||||
type LegacyConversationType = {
|
type LegacyConversationType = {
|
||||||
id: string;
|
id: string;
|
||||||
groupId: 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(
|
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 updateToSchemaVersion85 from './85-add-kyber-keys';
|
||||||
import updateToSchemaVersion86 from './86-story-replies-index';
|
import updateToSchemaVersion86 from './86-story-replies-index';
|
||||||
import updateToSchemaVersion87 from './87-calls-history-table';
|
import updateToSchemaVersion87 from './87-calls-history-table';
|
||||||
|
import updateToSchemaVersion88 from './88-service-ids';
|
||||||
|
|
||||||
function updateToSchemaVersion1(
|
function updateToSchemaVersion1(
|
||||||
currentVersion: number,
|
currentVersion: number,
|
||||||
|
@ -1996,6 +1997,7 @@ export const SCHEMA_VERSIONS = [
|
||||||
updateToSchemaVersion85,
|
updateToSchemaVersion85,
|
||||||
updateToSchemaVersion86,
|
updateToSchemaVersion86,
|
||||||
updateToSchemaVersion87,
|
updateToSchemaVersion87,
|
||||||
|
updateToSchemaVersion88,
|
||||||
];
|
];
|
||||||
|
|
||||||
export function updateSchema(db: Database, logger: LoggerType): void {
|
export function updateSchema(db: Database, logger: LoggerType): void {
|
||||||
|
|
|
@ -62,9 +62,9 @@ function checkForAccount(
|
||||||
}
|
}
|
||||||
|
|
||||||
const conversation = window.ConversationController.get(phoneNumber);
|
const conversation = window.ConversationController.get(phoneNumber);
|
||||||
if (conversation && conversation.get('uuid')) {
|
if (conversation && conversation.getServiceId()) {
|
||||||
log.info(`checkForAccount: found ${phoneNumber} in existing contacts`);
|
log.info(`checkForAccount: found ${phoneNumber} in existing contacts`);
|
||||||
const serviceId = conversation.get('uuid');
|
const serviceId = conversation.getServiceId();
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'accounts/UPDATE',
|
type: 'accounts/UPDATE',
|
||||||
|
@ -93,8 +93,10 @@ function checkForAccount(
|
||||||
|
|
||||||
log.info(`checkForAccount: looking ${phoneNumber} up on server`);
|
log.info(`checkForAccount: looking ${phoneNumber} up on server`);
|
||||||
try {
|
try {
|
||||||
const uuidLookup = await getServiceIdsForE164s(server, [phoneNumber]);
|
const serviceIdLookup = await getServiceIdsForE164s(server, [
|
||||||
const maybePair = uuidLookup.get(phoneNumber);
|
phoneNumber,
|
||||||
|
]);
|
||||||
|
const maybePair = serviceIdLookup.get(phoneNumber);
|
||||||
|
|
||||||
if (maybePair) {
|
if (maybePair) {
|
||||||
const { conversation: maybeMerged } =
|
const { conversation: maybeMerged } =
|
||||||
|
@ -104,7 +106,7 @@ function checkForAccount(
|
||||||
e164: phoneNumber,
|
e164: phoneNumber,
|
||||||
reason: 'checkForAccount',
|
reason: 'checkForAccount',
|
||||||
});
|
});
|
||||||
serviceId = maybeMerged.get('uuid');
|
serviceId = maybeMerged.getServiceId();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error('checkForAccount:', Errors.toLogFormat(error));
|
log.error('checkForAccount:', Errors.toLogFormat(error));
|
||||||
|
|
|
@ -936,7 +936,7 @@ function keyChanged(
|
||||||
if (activeCall.callMode === CallMode.Group) {
|
if (activeCall.callMode === CallMode.Group) {
|
||||||
const acisChanged = new Set(activeCallState.safetyNumberChangedAcis);
|
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.
|
// matches one of the participants in the group call.
|
||||||
activeCall.remoteParticipants.forEach(participant => {
|
activeCall.remoteParticipants.forEach(participant => {
|
||||||
if (participant.aci === payload.aci) {
|
if (participant.aci === payload.aci) {
|
||||||
|
|
|
@ -35,6 +35,7 @@ import {
|
||||||
REMOVE_PREVIEW as REMOVE_LINK_PREVIEW,
|
REMOVE_PREVIEW as REMOVE_LINK_PREVIEW,
|
||||||
} from './linkPreviews';
|
} from './linkPreviews';
|
||||||
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
||||||
|
import type { AciString } from '../../types/ServiceId';
|
||||||
import { completeRecording } from './audioRecorder';
|
import { completeRecording } from './audioRecorder';
|
||||||
import { RecordingState } from '../../types/AudioRecorder';
|
import { RecordingState } from '../../types/AudioRecorder';
|
||||||
import { SHOW_TOAST } from './toast';
|
import { SHOW_TOAST } from './toast';
|
||||||
|
@ -526,7 +527,7 @@ function sendEditedMessage(
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
options: WithPreSendChecksOptions & {
|
options: WithPreSendChecksOptions & {
|
||||||
targetMessageId: string;
|
targetMessageId: string;
|
||||||
quoteAuthorUuid?: string;
|
quoteAuthorAci?: AciString;
|
||||||
quoteSentAt?: number;
|
quoteSentAt?: number;
|
||||||
}
|
}
|
||||||
): ThunkAction<
|
): ThunkAction<
|
||||||
|
@ -545,7 +546,7 @@ function sendEditedMessage(
|
||||||
message = '',
|
message = '',
|
||||||
bodyRanges,
|
bodyRanges,
|
||||||
quoteSentAt,
|
quoteSentAt,
|
||||||
quoteAuthorUuid,
|
quoteAuthorAci,
|
||||||
targetMessageId,
|
targetMessageId,
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
|
@ -559,7 +560,7 @@ function sendEditedMessage(
|
||||||
body: message,
|
body: message,
|
||||||
bodyRanges,
|
bodyRanges,
|
||||||
preview: getLinkPreviewForSend(message),
|
preview: getLinkPreviewForSend(message),
|
||||||
quoteAuthorUuid,
|
quoteAuthorAci,
|
||||||
quoteSentAt,
|
quoteSentAt,
|
||||||
targetMessageId,
|
targetMessageId,
|
||||||
});
|
});
|
||||||
|
|
|
@ -219,7 +219,7 @@ export type DraftPreviewType = ReadonlyDeep<{
|
||||||
export type ConversationType = ReadonlyDeep<
|
export type ConversationType = ReadonlyDeep<
|
||||||
{
|
{
|
||||||
id: string;
|
id: string;
|
||||||
uuid?: ServiceIdString;
|
serviceId?: ServiceIdString;
|
||||||
pni?: PniString;
|
pni?: PniString;
|
||||||
e164?: string;
|
e164?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
@ -274,15 +274,15 @@ export type ConversationType = ReadonlyDeep<
|
||||||
announcementsOnlyReady?: boolean;
|
announcementsOnlyReady?: boolean;
|
||||||
expireTimer?: DurationInSeconds;
|
expireTimer?: DurationInSeconds;
|
||||||
memberships?: ReadonlyArray<{
|
memberships?: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
isAdmin: boolean;
|
isAdmin: boolean;
|
||||||
}>;
|
}>;
|
||||||
pendingMemberships?: ReadonlyArray<{
|
pendingMemberships?: ReadonlyArray<{
|
||||||
uuid: ServiceIdString;
|
serviceId: ServiceIdString;
|
||||||
addedByUserId?: AciString;
|
addedByUserId?: AciString;
|
||||||
}>;
|
}>;
|
||||||
pendingApprovalMemberships?: ReadonlyArray<{
|
pendingApprovalMemberships?: ReadonlyArray<{
|
||||||
uuid: AciString;
|
aci: AciString;
|
||||||
}>;
|
}>;
|
||||||
bannedMemberships?: ReadonlyArray<ServiceIdString>;
|
bannedMemberships?: ReadonlyArray<ServiceIdString>;
|
||||||
muteExpiresAt?: number;
|
muteExpiresAt?: number;
|
||||||
|
@ -474,7 +474,7 @@ export type ConversationsStateType = Readonly<{
|
||||||
invitedServiceIdsForNewlyCreatedGroup?: ReadonlyArray<ServiceIdString>;
|
invitedServiceIdsForNewlyCreatedGroup?: ReadonlyArray<ServiceIdString>;
|
||||||
conversationLookup: ConversationLookupType;
|
conversationLookup: ConversationLookupType;
|
||||||
conversationsByE164: ConversationLookupType;
|
conversationsByE164: ConversationLookupType;
|
||||||
conversationsByUuid: ConversationLookupType;
|
conversationsByServiceId: ConversationLookupType;
|
||||||
conversationsByGroupId: ConversationLookupType;
|
conversationsByGroupId: ConversationLookupType;
|
||||||
conversationsByUsername: ConversationLookupType;
|
conversationsByUsername: ConversationLookupType;
|
||||||
selectedConversationId?: string;
|
selectedConversationId?: string;
|
||||||
|
@ -576,7 +576,7 @@ export type CancelVerificationDataByConversationActionType = ReadonlyDeep<{
|
||||||
type ClearGroupCreationErrorActionType = ReadonlyDeep<{
|
type ClearGroupCreationErrorActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_GROUP_CREATION_ERROR';
|
type: 'CLEAR_GROUP_CREATION_ERROR';
|
||||||
}>;
|
}>;
|
||||||
type ClearInvitedUuidsForNewlyCreatedGroupActionType = ReadonlyDeep<{
|
type ClearInvitedServiceIdsForNewlyCreatedGroupActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_INVITED_SERVICE_IDS_FOR_NEWLY_CREATED_GROUP';
|
type: 'CLEAR_INVITED_SERVICE_IDS_FOR_NEWLY_CREATED_GROUP';
|
||||||
}>;
|
}>;
|
||||||
type ClearVerificationDataByConversationActionType = ReadonlyDeep<{
|
type ClearVerificationDataByConversationActionType = ReadonlyDeep<{
|
||||||
|
@ -944,7 +944,7 @@ export type ConversationActionType =
|
||||||
| CancelVerificationDataByConversationActionType
|
| CancelVerificationDataByConversationActionType
|
||||||
| ClearCancelledVerificationActionType
|
| ClearCancelledVerificationActionType
|
||||||
| ClearGroupCreationErrorActionType
|
| ClearGroupCreationErrorActionType
|
||||||
| ClearInvitedUuidsForNewlyCreatedGroupActionType
|
| ClearInvitedServiceIdsForNewlyCreatedGroupActionType
|
||||||
| ClearTargetedMessageActionType
|
| ClearTargetedMessageActionType
|
||||||
| ClearUnreadMetricsActionType
|
| ClearUnreadMetricsActionType
|
||||||
| ClearVerificationDataByConversationActionType
|
| ClearVerificationDataByConversationActionType
|
||||||
|
@ -1022,7 +1022,7 @@ export const actions = {
|
||||||
changeHasGroupLink,
|
changeHasGroupLink,
|
||||||
clearCancelledConversationVerification,
|
clearCancelledConversationVerification,
|
||||||
clearGroupCreationError,
|
clearGroupCreationError,
|
||||||
clearInvitedUuidsForNewlyCreatedGroup,
|
clearInvitedServiceIdsForNewlyCreatedGroup,
|
||||||
clearTargetedMessage,
|
clearTargetedMessage,
|
||||||
clearUnreadMetrics,
|
clearUnreadMetrics,
|
||||||
closeContactSpoofingReview,
|
closeContactSpoofingReview,
|
||||||
|
@ -1863,7 +1863,11 @@ export const markViewed = (messageId: string): void => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const senderE164 = message.get('source');
|
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 });
|
const timestamp = getMessageSentTimestamp(message.attributes, { log });
|
||||||
|
|
||||||
message.set(messageUpdaterMarkViewed(message.attributes, Date.now()));
|
message.set(messageUpdaterMarkViewed(message.attributes, Date.now()));
|
||||||
|
@ -1881,7 +1885,7 @@ export const markViewed = (messageId: string): void => {
|
||||||
messageId,
|
messageId,
|
||||||
conversationId,
|
conversationId,
|
||||||
senderE164,
|
senderE164,
|
||||||
senderUuid,
|
senderAci,
|
||||||
timestamp,
|
timestamp,
|
||||||
isDirectConversation: convoAttributes
|
isDirectConversation: convoAttributes
|
||||||
? isDirectConversation(convoAttributes)
|
? isDirectConversation(convoAttributes)
|
||||||
|
@ -1898,7 +1902,7 @@ export const markViewed = (messageId: string): void => {
|
||||||
{
|
{
|
||||||
messageId,
|
messageId,
|
||||||
senderE164,
|
senderE164,
|
||||||
senderUuid,
|
senderAci,
|
||||||
timestamp,
|
timestamp,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -2578,7 +2582,7 @@ function createGroup(
|
||||||
type: 'CREATE_GROUP_FULFILLED',
|
type: 'CREATE_GROUP_FULFILLED',
|
||||||
payload: {
|
payload: {
|
||||||
invitedServiceIds: (conversation.get('pendingMembersV2') || []).map(
|
invitedServiceIds: (conversation.get('pendingMembersV2') || []).map(
|
||||||
member => member.uuid
|
member => member.serviceId
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -2706,11 +2710,11 @@ function conversationStoppedByMissingVerification(payload: {
|
||||||
untrustedServiceIds: ReadonlyArray<ServiceIdString>;
|
untrustedServiceIds: ReadonlyArray<ServiceIdString>;
|
||||||
}): ConversationStoppedByMissingVerificationActionType {
|
}): ConversationStoppedByMissingVerificationActionType {
|
||||||
// Fetching profiles to ensure that we have their latest identity key in storage
|
// Fetching profiles to ensure that we have their latest identity key in storage
|
||||||
payload.untrustedServiceIds.forEach(uuid => {
|
payload.untrustedServiceIds.forEach(serviceId => {
|
||||||
const conversation = window.ConversationController.get(uuid);
|
const conversation = window.ConversationController.get(serviceId);
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
log.error(
|
log.error(
|
||||||
`conversationStoppedByMissingVerification: uuid ${uuid} not found!`
|
`conversationStoppedByMissingVerification: serviceId ${serviceId} not found!`
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3405,8 +3409,8 @@ function loadRecentMediaItems(
|
||||||
message: {
|
message: {
|
||||||
attachments: message.attachments || [],
|
attachments: message.attachments || [],
|
||||||
conversationId:
|
conversationId:
|
||||||
window.ConversationController.get(message.sourceUuid)?.id ||
|
window.ConversationController.get(message.sourceServiceId)
|
||||||
message.conversationId,
|
?.id || message.conversationId,
|
||||||
id: message.id,
|
id: message.id,
|
||||||
received_at: message.received_at,
|
received_at: message.received_at,
|
||||||
received_at_ms: Number(message.received_at_ms),
|
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' };
|
return { type: 'CLEAR_INVITED_SERVICE_IDS_FOR_NEWLY_CREATED_GROUP' };
|
||||||
}
|
}
|
||||||
function clearGroupCreationError(): ClearGroupCreationErrorActionType {
|
function clearGroupCreationError(): ClearGroupCreationErrorActionType {
|
||||||
|
@ -4130,7 +4134,7 @@ export function getEmptyState(): ConversationsStateType {
|
||||||
return {
|
return {
|
||||||
conversationLookup: {},
|
conversationLookup: {},
|
||||||
conversationsByE164: {},
|
conversationsByE164: {},
|
||||||
conversationsByUuid: {},
|
conversationsByServiceId: {},
|
||||||
conversationsByGroupId: {},
|
conversationsByGroupId: {},
|
||||||
conversationsByUsername: {},
|
conversationsByUsername: {},
|
||||||
verificationDataByConversation: {},
|
verificationDataByConversation: {},
|
||||||
|
@ -4158,13 +4162,13 @@ export function updateConversationLookups(
|
||||||
): Pick<
|
): Pick<
|
||||||
ConversationsStateType,
|
ConversationsStateType,
|
||||||
| 'conversationsByE164'
|
| 'conversationsByE164'
|
||||||
| 'conversationsByUuid'
|
| 'conversationsByServiceId'
|
||||||
| 'conversationsByGroupId'
|
| 'conversationsByGroupId'
|
||||||
| 'conversationsByUsername'
|
| 'conversationsByUsername'
|
||||||
> {
|
> {
|
||||||
const result = {
|
const result = {
|
||||||
conversationsByE164: state.conversationsByE164,
|
conversationsByE164: state.conversationsByE164,
|
||||||
conversationsByUuid: state.conversationsByUuid,
|
conversationsByServiceId: state.conversationsByServiceId,
|
||||||
conversationsByGroupId: state.conversationsByGroupId,
|
conversationsByGroupId: state.conversationsByGroupId,
|
||||||
conversationsByUsername: state.conversationsByUsername,
|
conversationsByUsername: state.conversationsByUsername,
|
||||||
};
|
};
|
||||||
|
@ -4172,11 +4176,17 @@ export function updateConversationLookups(
|
||||||
if (removed && removed.e164) {
|
if (removed && removed.e164) {
|
||||||
result.conversationsByE164 = omit(result.conversationsByE164, removed.e164);
|
result.conversationsByE164 = omit(result.conversationsByE164, removed.e164);
|
||||||
}
|
}
|
||||||
if (removed && removed.uuid) {
|
if (removed && removed.serviceId) {
|
||||||
result.conversationsByUuid = omit(result.conversationsByUuid, removed.uuid);
|
result.conversationsByServiceId = omit(
|
||||||
|
result.conversationsByServiceId,
|
||||||
|
removed.serviceId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (removed && removed.pni) {
|
if (removed && removed.pni) {
|
||||||
result.conversationsByUuid = omit(result.conversationsByUuid, removed.pni);
|
result.conversationsByServiceId = omit(
|
||||||
|
result.conversationsByServiceId,
|
||||||
|
removed.pni
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (removed && removed.groupId) {
|
if (removed && removed.groupId) {
|
||||||
result.conversationsByGroupId = omit(
|
result.conversationsByGroupId = omit(
|
||||||
|
@ -4197,15 +4207,15 @@ export function updateConversationLookups(
|
||||||
[added.e164]: added,
|
[added.e164]: added,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (added && added.uuid) {
|
if (added && added.serviceId) {
|
||||||
result.conversationsByUuid = {
|
result.conversationsByServiceId = {
|
||||||
...result.conversationsByUuid,
|
...result.conversationsByServiceId,
|
||||||
[added.uuid]: added,
|
[added.serviceId]: added,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (added && added.pni) {
|
if (added && added.pni) {
|
||||||
result.conversationsByUuid = {
|
result.conversationsByServiceId = {
|
||||||
...result.conversationsByUuid,
|
...result.conversationsByServiceId,
|
||||||
[added.pni]: added,
|
[added.pni]: added,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4285,12 +4295,14 @@ function getVerificationDataForConversation({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const existingUuids = distributionId
|
const existingServiceIds = distributionId
|
||||||
? existing.byDistributionId?.[distributionId]?.serviceIdsNeedingVerification
|
? existing.byDistributionId?.[distributionId]?.serviceIdsNeedingVerification
|
||||||
: existing.serviceIdsNeedingVerification;
|
: existing.serviceIdsNeedingVerification;
|
||||||
|
|
||||||
const serviceIdsNeedingVerification: ReadonlyArray<ServiceIdString> =
|
const serviceIdsNeedingVerification: ReadonlyArray<ServiceIdString> =
|
||||||
Array.from(new Set([...(existingUuids || []), ...untrustedServiceIds]));
|
Array.from(
|
||||||
|
new Set([...(existingServiceIds || []), ...untrustedServiceIds])
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[conversationId]: {
|
[conversationId]: {
|
||||||
|
@ -4800,7 +4812,9 @@ export function reducer(
|
||||||
membersToRemove,
|
membersToRemove,
|
||||||
membersToAdd,
|
membersToAdd,
|
||||||
} = action.payload;
|
} = action.payload;
|
||||||
const removedUuids = new Set(isBlockList ? membersToAdd : membersToRemove);
|
const removedServiceIds = new Set(
|
||||||
|
isBlockList ? membersToAdd : membersToRemove
|
||||||
|
);
|
||||||
|
|
||||||
const nextVerificationData = visitListsInVerificationData(
|
const nextVerificationData = visitListsInVerificationData(
|
||||||
state.verificationDataByConversation,
|
state.verificationDataByConversation,
|
||||||
|
@ -4808,7 +4822,7 @@ export function reducer(
|
||||||
if (listId === id) {
|
if (listId === id) {
|
||||||
const serviceIdsNeedingVerification =
|
const serviceIdsNeedingVerification =
|
||||||
data.serviceIdsNeedingVerification.filter(
|
data.serviceIdsNeedingVerification.filter(
|
||||||
uuid => !removedUuids.has(uuid)
|
serviceId => !removedServiceIds.has(serviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!serviceIdsNeedingVerification.length) {
|
if (!serviceIdsNeedingVerification.length) {
|
||||||
|
@ -4857,7 +4871,7 @@ export function reducer(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (action.type === HIDE_MY_STORIES_FROM) {
|
if (action.type === HIDE_MY_STORIES_FROM) {
|
||||||
const removedUuids = new Set(action.payload);
|
const removedServiceIds = new Set(action.payload);
|
||||||
|
|
||||||
const nextVerificationData = visitListsInVerificationData(
|
const nextVerificationData = visitListsInVerificationData(
|
||||||
state.verificationDataByConversation,
|
state.verificationDataByConversation,
|
||||||
|
@ -4865,7 +4879,7 @@ export function reducer(
|
||||||
if (MY_STORY_ID === id) {
|
if (MY_STORY_ID === id) {
|
||||||
const serviceIdsNeedingVerification =
|
const serviceIdsNeedingVerification =
|
||||||
data.serviceIdsNeedingVerification.filter(
|
data.serviceIdsNeedingVerification.filter(
|
||||||
uuid => !removedUuids.has(uuid)
|
serviceId => !removedServiceIds.has(serviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!serviceIdsNeedingVerification.length) {
|
if (!serviceIdsNeedingVerification.length) {
|
||||||
|
@ -4893,15 +4907,15 @@ export function reducer(
|
||||||
}
|
}
|
||||||
if (action.type === VIEWERS_CHANGED) {
|
if (action.type === VIEWERS_CHANGED) {
|
||||||
const { listId, memberServiceIds } = action.payload;
|
const { listId, memberServiceIds } = action.payload;
|
||||||
const newUuids = new Set(memberServiceIds);
|
const newServiceIds = new Set(memberServiceIds);
|
||||||
|
|
||||||
const nextVerificationData = visitListsInVerificationData(
|
const nextVerificationData = visitListsInVerificationData(
|
||||||
state.verificationDataByConversation,
|
state.verificationDataByConversation,
|
||||||
(id, data): DistributionVerificationData | undefined => {
|
(id, data): DistributionVerificationData | undefined => {
|
||||||
if (listId === id) {
|
if (listId === id) {
|
||||||
const serviceIdsNeedingVerification =
|
const serviceIdsNeedingVerification =
|
||||||
data.serviceIdsNeedingVerification.filter(uuid =>
|
data.serviceIdsNeedingVerification.filter(serviceId =>
|
||||||
newUuids.has(uuid)
|
newServiceIds.has(serviceId)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!serviceIdsNeedingVerification.length) {
|
if (!serviceIdsNeedingVerification.length) {
|
||||||
|
@ -5928,7 +5942,7 @@ export function reducer(
|
||||||
if (!composer) {
|
if (!composer) {
|
||||||
assertDev(
|
assertDev(
|
||||||
false,
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -5938,7 +5952,7 @@ export function reducer(
|
||||||
) {
|
) {
|
||||||
assertDev(
|
assertDev(
|
||||||
false,
|
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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -508,7 +508,7 @@ function showGV2MigrationDialog(
|
||||||
});
|
});
|
||||||
|
|
||||||
const invitedMemberIds = pendingMembersV2.map(
|
const invitedMemberIds = pendingMembersV2.map(
|
||||||
(item: GroupV2PendingMemberType) => item.uuid
|
(item: GroupV2PendingMemberType) => item.serviceId
|
||||||
);
|
);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -264,7 +264,7 @@ function showLightbox(opts: {
|
||||||
|
|
||||||
const authorId =
|
const authorId =
|
||||||
window.ConversationController.lookupOrCreate({
|
window.ConversationController.lookupOrCreate({
|
||||||
uuid: message.get('sourceUuid'),
|
serviceId: message.get('sourceServiceId'),
|
||||||
e164: message.get('source'),
|
e164: message.get('source'),
|
||||||
reason: 'conversation_view.showLightBox',
|
reason: 'conversation_view.showLightBox',
|
||||||
})?.id || message.get('conversationId');
|
})?.id || message.get('conversationId');
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue