diff --git a/ts/components/conversation/message/message-content/MessageAvatar.tsx b/ts/components/conversation/message/message-content/MessageAvatar.tsx index 375b3158a..93cc83753 100644 --- a/ts/components/conversation/message/message-content/MessageAvatar.tsx +++ b/ts/components/conversation/message/message-content/MessageAvatar.tsx @@ -63,7 +63,7 @@ export const MessageAvatar = (props: Props) => { // public chat but session id not blinded. disable showing user details if we do not have an active convo with that user. // an unactive convo with that user means that we never chatted with that id directyly, but only through a sogs const convoWithSender = getConversationController().get(sender); - if (!convoWithSender || !convoWithSender.get('active_at')) { + if (!convoWithSender || !convoWithSender.getActiveAt()) { // for some time, we might still get some unblinded messages, as in message sent unblinded because // * older clients still send unblinded message and those are allowed by sogs if they doesn't enforce blinding // * new clients still send unblinded message and those are allowed by sogs if it doesn't enforce blinding diff --git a/ts/components/dialog/InviteContactsDialog.tsx b/ts/components/dialog/InviteContactsDialog.tsx index 2916f879c..cfd3237a4 100644 --- a/ts/components/dialog/InviteContactsDialog.tsx +++ b/ts/components/dialog/InviteContactsDialog.tsx @@ -73,13 +73,13 @@ const submitForClosedGroup = async (convoId: string, pubkeys: Array) => // closed group chats const ourPK = UserUtils.getOurPubKeyStrFromCache(); // we only care about real members. If a member is currently a zombie we have to be able to add him back - let existingMembers = convo.get('members') || []; + let existingMembers = convo.getGroupMembers() || []; // at least make sure it's an array if (!Array.isArray(existingMembers)) { existingMembers = []; } existingMembers = _.compact(existingMembers); - const existingZombies = convo.get('zombies') || []; + const existingZombies = convo.getGroupZombies() || []; const newMembers = pubkeys.filter(d => !existingMembers.includes(d)); if (newMembers.length > 0) { diff --git a/ts/components/dialog/UpdateGroupMembersDialog.tsx b/ts/components/dialog/UpdateGroupMembersDialog.tsx index dfd58a7af..6b99cba3c 100644 --- a/ts/components/dialog/UpdateGroupMembersDialog.tsx +++ b/ts/components/dialog/UpdateGroupMembersDialog.tsx @@ -138,8 +138,8 @@ async function onSubmit(convoId: string, membersAfterUpdate: Array) { // We consider that the admin ALWAYS wants to remove zombies (actually they should be removed // automatically by him when the LEFT message is received) - const existingMembers = convoFound.get('members') || []; - const existingZombies = convoFound.get('zombies') || []; + const existingMembers = convoFound.getGroupMembers() || []; + const existingZombies = convoFound.getGroupZombies() || []; const allExistingMembersWithZombies = _.uniq(existingMembers.concat(existingZombies)); @@ -168,7 +168,7 @@ async function onSubmit(convoId: string, membersAfterUpdate: Array) { void initiateClosedGroupUpdate( convoId, - convoFound.get('displayNameInProfile') || 'Unknown', + convoFound.getRealSessionUsername() || 'Unknown', filteredMembers ); } diff --git a/ts/components/dialog/UpdateGroupNameDialog.tsx b/ts/components/dialog/UpdateGroupNameDialog.tsx index 3676c60a7..cf8003be8 100644 --- a/ts/components/dialog/UpdateGroupNameDialog.tsx +++ b/ts/components/dialog/UpdateGroupNameDialog.tsx @@ -76,7 +76,7 @@ export class UpdateGroupNameDialog extends React.Component { objectUrl: newAvatarObjecturl, }); } else { - const members = this.convo.get('members') || []; + const members = this.convo.getGroupMembers() || []; void initiateClosedGroupUpdate(this.convo.id, trimmedGroupName, members); } diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index fa143f70b..3f28296b1 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -205,7 +205,7 @@ export async function showUpdateGroupNameByConvoId(conversationId: string) { // make sure all the members' convo exists so we can add or remove them await Promise.all( conversation - .get('members') + .getGroupMembers() .map(m => getConversationController().getOrCreateAndWait(m, ConversationTypeEnum.PRIVATE)) ); } @@ -218,7 +218,7 @@ export async function showUpdateGroupMembersByConvoId(conversationId: string) { // make sure all the members' convo exists so we can add or remove them await Promise.all( conversation - .get('members') + .getGroupMembers() .map(m => getConversationController().getOrCreateAndWait(m, ConversationTypeEnum.PRIVATE)) ); } @@ -310,7 +310,7 @@ export async function setNotificationForConvoId( ) { const conversation = getConversationController().get(conversationId); - const existingSettings = conversation.get('triggerNotificationsFor'); + const existingSettings = conversation.getNotificationsFor(); if (existingSettings !== selected) { conversation.set({ triggerNotificationsFor: selected }); await conversation.commit(); @@ -403,7 +403,7 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) { const ourConvoProfileKey = getConversationController() .get(UserUtils.getOurPubKeyStrFromCache()) - ?.get('profileKey') || null; + ?.getProfileKey() || null; profileKey = ourConvoProfileKey ? fromHexToArray(ourConvoProfileKey) : null; if (!profileKey) { @@ -452,7 +452,7 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) { }); // Replace our temporary image with the attachment pointer from the server: ourConvo.set('avatarInProfile', undefined); - const displayName = ourConvo.get('displayNameInProfile'); + const displayName = ourConvo.getRealSessionUsername(); // write the profileKey even if it did not change ourConvo.set({ profileKey: toHex(profileKey) }); @@ -480,8 +480,8 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) { ); } return { - avatarPointer: ourConvo.get('avatarPointer'), - profileKey: ourConvo.get('profileKey'), + avatarPointer: ourConvo.getAvatarPointer(), + profileKey: ourConvo.getProfileKey(), }; } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 1cac2c805..43e06366a 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -117,6 +117,7 @@ import { SessionUtilUserProfile } from '../session/utils/libsession/libsession_u import { ReduxSogsRoomInfos } from '../state/ducks/sogsRoomInfo'; import { getLibGroupAdminsOutsideRedux, + getLibGroupMembersOutsideRedux, getLibGroupNameOutsideRedux, } from '../state/selectors/groups'; import { @@ -262,7 +263,7 @@ export class ConversationModel extends Backbone.Model { * For instance, all of the conversations created when receiving a community are not active, until we start directly talking with them (or they do). */ public isActive() { - return Boolean(this.get('active_at')); + return Boolean(this.getActiveAt()); } /** @@ -273,7 +274,7 @@ export class ConversationModel extends Backbone.Model { * - a legacy group is kept visible if we leave it, until we explicitely delete it. At that time, it is removed completely and not marked hidden */ public isHidden() { - const priority = this.get('priority') || CONVERSATION_PRIORITIES.default; + const priority = this.getPriority(); return this.isPrivate() && priority === CONVERSATION_PRIORITIES.hidden; } @@ -281,6 +282,14 @@ export class ConversationModel extends Backbone.Model { await deleteExternalFilesOfConversation(this.attributes); } + public getPriority() { + return this.get('priority') || CONVERSATION_PRIORITIES.default; + } + + public getNotificationsFor() { + return this.get('triggerNotificationsFor'); + } + public getConversationModelProps(): ReduxConversationType { const isPublic = this.isPublic(); @@ -288,14 +297,14 @@ export class ConversationModel extends Backbone.Model { const isPrivate = this.isPrivate(); const weAreAdmin = this.weAreAdminUnblinded(); - const currentNotificationSetting = this.get('triggerNotificationsFor'); - const priorityFromDb = this.get('priority'); + const currentNotificationSetting = this.getNotificationsFor(); + const priorityFromDb = this.getPriority(); // To reduce the redux store size, only set fields which cannot be undefined. // For instance, a boolean can usually be not set if false, etc const toRet: ReduxConversationType = { id: this.id as string, - activeAt: this.get('active_at'), + activeAt: this.getActiveAt(), type: this.get('type'), }; @@ -347,8 +356,8 @@ export class ConversationModel extends Backbone.Model { toRet.currentNotificationSetting = currentNotificationSetting; } - if (this.get('displayNameInProfile')) { - toRet.displayNameInProfile = this.get('displayNameInProfile'); + if (this.getRealSessionUsername()) { + toRet.displayNameInProfile = this.getRealSessionUsername(); } if (this.get('nickname')) { toRet.nickname = this.get('nickname'); @@ -367,7 +376,7 @@ export class ConversationModel extends Backbone.Model { } // those are values coming only from both the DB or the wrapper. Currently we display the data from the DB if (this.isClosedGroup()) { - toRet.members = this.get('members') || []; + toRet.members = this.getGroupMembers() || []; } // those are values coming only from both the DB or the wrapper. Currently we display the data from the DB @@ -378,14 +387,14 @@ export class ConversationModel extends Backbone.Model { // those are values coming only from the DB when this is a closed group if (this.isClosedGroup()) { - if (this.get('isKickedFromGroup')) { - toRet.isKickedFromGroup = this.get('isKickedFromGroup'); + if (this.isKickedFromGroup()) { + toRet.isKickedFromGroup = this.isKickedFromGroup(); } - if (this.get('left')) { - toRet.left = this.get('left'); + if (this.isLeft()) { + toRet.left = this.isLeft(); } // to be dropped once we get rid of the legacy closed groups - const zombies = this.get('zombies') || []; + const zombies = this.getGroupZombies() || []; if (zombies?.length) { toRet.zombies = uniq(zombies); } @@ -656,7 +665,7 @@ export class ConversationModel extends Backbone.Model { isApproved: this.isApproved(), isBlocked: this.isBlocked(), isPrivate: this.isPrivate(), - activeAt: this.get('active_at'), + activeAt: this.getActiveAt(), didApproveMe: this.didApproveMe(), }); } @@ -671,7 +680,7 @@ export class ConversationModel extends Backbone.Model { didApproveMe: this.didApproveMe() || false, isBlocked: this.isBlocked() || false, isPrivate: this.isPrivate() || false, - activeAt: this.get('active_at') || 0, + activeAt: this.getActiveAt() || 0, }); } @@ -1094,7 +1103,7 @@ export class ConversationModel extends Backbone.Model { this.set({ avatarInProfile: newProfile.avatarPath }); changes = true; } - const existingImageId = this.get('avatarImageId'); + const existingImageId = this.getAvatarImageId(); if (existingImageId !== newProfile.avatarImageId) { this.set({ avatarImageId: newProfile.avatarImageId }); @@ -1128,6 +1137,18 @@ export class ConversationModel extends Backbone.Model { return this.isPrivate() ? this.get('nickname') || undefined : undefined; } + public getAvatarImageId(): number | undefined { + return this.isPublic() ? this.get('avatarImageId') || undefined : undefined; + } + + public getProfileKey(): string | undefined { + return this.get('profileKey'); + } + + public getAvatarPointer(): string | undefined { + return this.get('avatarPointer'); + } + /** * @returns `getNickname` if a private convo and a nickname is set, or `getRealSessionUsername` */ @@ -1196,7 +1217,7 @@ export class ConversationModel extends Backbone.Model { priority: number, shouldCommit: boolean = true ): Promise { - if (priority !== this.get('priority')) { + if (priority !== this.getPriority()) { this.set({ priority, }); @@ -1229,7 +1250,7 @@ export class ConversationModel extends Backbone.Model { if (!this.isPrivate()) { return; } - const priority = this.get('priority'); + const priority = this.getPriority(); if (priority >= CONVERSATION_PRIORITIES.default) { this.set({ priority: CONVERSATION_PRIORITIES.hidden }); if (shouldCommit) { @@ -1244,7 +1265,7 @@ export class ConversationModel extends Backbone.Model { * A pinned cannot be hidden, as the it is all based on the same priority values. */ public async unhideIfNeeded(shouldCommit: boolean = true) { - const priority = this.get('priority'); + const priority = this.getPriority(); if (isFinite(priority) && priority < CONVERSATION_PRIORITIES.default) { this.set({ priority: CONVERSATION_PRIORITIES.default }); if (shouldCommit) { @@ -1445,7 +1466,7 @@ export class ConversationModel extends Backbone.Model { const profileKeyHex = toHex(profileKey); // profileKey is a string so we can compare it directly - if (this.get('profileKey') !== profileKeyHex) { + if (this.getProfileKey() !== profileKeyHex) { this.set({ profileKey: profileKeyHex, }); @@ -1457,7 +1478,7 @@ export class ConversationModel extends Backbone.Model { } public hasMember(pubkey: string) { - return includes(this.get('members'), pubkey); + return includes(this.getGroupMembers(), pubkey); } public hasReactions() { @@ -1488,7 +1509,7 @@ export class ConversationModel extends Backbone.Model { } public isPinned() { - const priority = this.get('priority'); + const priority = this.getPriority(); return isFinite(priority) && priority > CONVERSATION_PRIORITIES.default; } @@ -1519,7 +1540,7 @@ export class ConversationModel extends Backbone.Model { return window.i18n('you'); } - const profileName = this.get('displayNameInProfile'); + const profileName = this.getRealSessionUsername(); return profileName || PubKey.shorten(pubkey); } @@ -1587,7 +1608,7 @@ export class ConversationModel extends Backbone.Model { } // make sure the notifications are not muted for this convo (and not the source convo) - const convNotif = this.get('triggerNotificationsFor'); + const convNotif = this.getNotificationsFor(); if (convNotif === 'disabled') { window?.log?.info('notifications disabled for convo', this.idForLogging()); return; @@ -1644,7 +1665,7 @@ export class ConversationModel extends Backbone.Model { const conversationId = this.id; // make sure the notifications are not muted for this convo (and not the source convo) - const convNotif = this.get('triggerNotificationsFor'); + const convNotif = this.getNotificationsFor(); if (convNotif === 'disabled') { window?.log?.info( 'notifyIncomingCall: notifications disabled for convo', @@ -1704,6 +1725,60 @@ export class ConversationModel extends Backbone.Model { return groupAdmins && groupAdmins.length > 0 ? groupAdmins : []; } + public isKickedFromGroup(): boolean { + if (this.isClosedGroup()) { + if (this.isClosedGroupV3()) { + console.info('isKickedFromGroup using lib todo'); // debugger + } + return !!this.get('isKickedFromGroup'); + } + return false; + } + + public isLeft(): boolean { + if (this.isClosedGroup()) { + if (this.isClosedGroupV3()) { + console.info('isLeft using lib todo'); // debugger + } + return !!this.get('left'); + } + return false; + } + + public getActiveAt(): number | undefined { + return this.get('active_at'); + } + + public getLastJoinedTimestamp(): number { + if (this.isClosedGroup()) { + return this.get('lastJoinedTimestamp') || 0; + } + return 0; + } + + public getGroupMembers(): Array { + if (this.isClosedGroup()) { + if (this.isClosedGroupV3()) { + return getLibGroupMembersOutsideRedux(this.id); + } + const members = this.get('members'); + return members && members.length > 0 ? members : []; + } + return []; + } + + public getGroupZombies(): Array { + if (this.isClosedGroup()) { + // closed group with 03 prefix does not have the concepts of zombies + if (this.isClosedGroupV3()) { + return []; + } + const zombies = this.get('zombies'); + return zombies && zombies.length > 0 ? zombies : []; + } + return []; + } + private async sendMessageJob(message: MessageModel, expireTimer: number | undefined) { try { const { body, attachments, preview, quote, fileIdsToLink } = await message.uploadData(); @@ -1919,7 +1994,7 @@ export class ConversationModel extends Backbone.Model { } private async bouncyUpdateLastMessage() { - if (!this.id || !this.get('active_at') || this.isHidden()) { + if (!this.id || !this.getActiveAt() || this.isHidden()) { return; } const messages = await Data.getLastMessagesByConversation(this.id, 1, true); @@ -2336,7 +2411,7 @@ export class ConversationCollection extends Backbone.Collection) { super(models); this.comparator = (m: ConversationModel) => { - return -(m.get('active_at') || 0); + return -(m.getActiveAt() || 0); }; } } @@ -2379,7 +2454,7 @@ export function hasValidIncomingRequestValues({ isBlocked: boolean; isPrivate: boolean; didApproveMe: boolean; - activeAt: number; + activeAt: number | undefined; }): boolean { // if a convo is not active, it means we didn't get any messages nor sent any. const isActive = activeAt && isFinite(activeAt) && activeAt > 0; diff --git a/ts/models/message.ts b/ts/models/message.ts index a8da83b78..300495b43 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -436,7 +436,7 @@ export class MessageModel extends Backbone.Model { return undefined; } - if (this.getConversation()?.get('left')) { + if (this.getConversation()?.isLeft()) { return 'sent'; } diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.ts index ea0be9c0f..eef48d648 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.ts @@ -303,7 +303,7 @@ export async function handleNewClosedGroup( if (groupConvo) { // if we did not left this group, just add the keypair we got if not already there - if (!groupConvo.get('isKickedFromGroup') && !groupConvo.get('left')) { + if (!groupConvo.isKickedFromGroup() && !groupConvo.isLeft()) { const ecKeyPairAlreadyExistingConvo = new ECKeyPair( encryptionKeyPair!.publicKey, encryptionKeyPair!.privateKey @@ -542,7 +542,7 @@ async function performIfValid( } // Check that the message isn't from before the group was created - let lastJoinedTimestamp = convo.get('lastJoinedTimestamp'); + let lastJoinedTimestamp = convo.getLastJoinedTimestamp(); // might happen for existing groups if (!lastJoinedTimestamp) { const aYearAgo = Date.now() - 1000 * 60 * 24 * 365; @@ -562,7 +562,7 @@ async function performIfValid( } // Check that the sender is a member of the group (before the update) - const oldMembers = convo.get('members') || []; + const oldMembers = convo.getGroupMembers() || []; if (!oldMembers.includes(sender)) { window?.log?.error( `Error: closed group: ignoring closed group update message from non-member. ${sender} is not a current member.` @@ -600,7 +600,7 @@ async function handleClosedGroupNameChanged( const newName = groupUpdate.name; window?.log?.info(`Got a group update for group ${envelope.source}, type: NAME_CHANGED`); - if (newName !== convo.get('displayNameInProfile')) { + if (newName !== convo.getRealSessionUsername()) { const groupDiff: ClosedGroup.GroupDiff = { newName, }; @@ -628,7 +628,7 @@ async function handleClosedGroupMembersAdded( ) { const { members: addedMembersBinary } = groupUpdate; const addedMembers = (addedMembersBinary || []).map(toHex); - const oldMembers = convo.get('members') || []; + const oldMembers = convo.getGroupMembers() || []; const membersNotAlreadyPresent = addedMembers.filter(m => !oldMembers.includes(m)); window?.log?.info(`Got a group update for group ${envelope.source}, type: MEMBERS_ADDED`); @@ -696,7 +696,7 @@ async function handleClosedGroupMembersRemoved( shouldOnlyAddUpdateMessage: boolean // set this to true to not apply the change to the convo itself, just add the update in the conversation ) { // Check that the admin wasn't removed - const currentMembers = convo.get('members'); + const currentMembers = convo.getGroupMembers(); // removedMembers are all members in the diff const removedMembers = groupUpdate.members.map(toHex); // effectivelyRemovedMembers are the members which where effectively on this group before the update @@ -755,7 +755,7 @@ async function handleClosedGroupMembersRemoved( } // Update the group - const zombies = convo.get('zombies').filter(z => membersAfterUpdate.includes(z)); + const zombies = convo.getGroupZombies().filter(z => membersAfterUpdate.includes(z)); if (!shouldOnlyAddUpdateMessage) { convo.set({ members: membersAfterUpdate }); @@ -767,7 +767,7 @@ async function handleClosedGroupMembersRemoved( } function isUserAZombie(convo: ConversationModel, user: PubKey) { - return convo.get('zombies').includes(user.key); + return convo.getGroupZombies().includes(user.key); } /** @@ -779,7 +779,7 @@ function addMemberToZombies( userToAdd: PubKey, convo: ConversationModel ): boolean { - const zombies = convo.get('zombies'); + const zombies = convo.getGroupZombies(); const isAlreadyZombie = isUserAZombie(convo, userToAdd); if (isAlreadyZombie) { @@ -799,7 +799,7 @@ function removeMemberFromZombies( userToAdd: PubKey, convo: ConversationModel ): boolean { - const zombies = convo.get('zombies'); + const zombies = convo.getGroupZombies(); const isAlreadyAZombie = isUserAZombie(convo, userToAdd); if (!isAlreadyAZombie) { @@ -840,7 +840,7 @@ async function handleClosedGroupMemberLeft( const didAdminLeave = convo.getGroupAdmins().includes(sender) || false; // If the admin leaves the group is disbanded // otherwise, we remove the sender from the list of current members in this group - const oldMembers = convo.get('members') || []; + const oldMembers = convo.getGroupMembers() || []; const newMembers = oldMembers.filter(s => s !== sender); window?.log?.info(`Got a group update for group ${envelope.source}, type: MEMBER_LEFT`); diff --git a/ts/receiver/configMessage.ts b/ts/receiver/configMessage.ts index d705280e7..131d9c9d8 100644 --- a/ts/receiver/configMessage.ts +++ b/ts/receiver/configMessage.ts @@ -320,7 +320,7 @@ async function handleContactsUpdate() { changes = true; } - const currentPriority = contactConvo.get('priority'); + const currentPriority = contactConvo.getPriority(); if (wrapperConvo.priority !== currentPriority) { if (wrapperConvo.priority === CONVERSATION_PRIORITIES.hidden) { window.log.info( @@ -348,7 +348,7 @@ async function handleContactsUpdate() { // } // we want to set the active_at to the created_at timestamp if active_at is unset, so that it shows up in our list. - if (!contactConvo.get('active_at') && wrapperConvo.createdAtSeconds) { + if (!contactConvo.getActiveAt() && wrapperConvo.createdAtSeconds) { contactConvo.set({ active_at: wrapperConvo.createdAtSeconds * 1000 }); changes = true; } @@ -542,6 +542,7 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) { const members = fromWrapper.members.map(m => m.pubkeyHex); const admins = fromWrapper.members.filter(m => m.isAdmin).map(m => m.pubkeyHex); + const activeAt = legacyGroupConvo.getActiveAt(); // then for all the existing legacy group in the wrapper, we need to override the field of what we have in the DB with what is in the wrapper // We only set group admins on group creation const groupDetails: ClosedGroup.GroupInfo = { @@ -550,9 +551,8 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) { members, admins, activeAt: - !!legacyGroupConvo.get('active_at') && - legacyGroupConvo.get('active_at') < latestEnvelopeTimestamp - ? legacyGroupConvo.get('active_at') + !!activeAt && activeAt < latestEnvelopeTimestamp + ? legacyGroupConvo.getActiveAt() : latestEnvelopeTimestamp, }; @@ -560,7 +560,7 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) { let changes = await legacyGroupConvo.setPriorityFromWrapper(fromWrapper.priority, false); - const existingTimestampMs = legacyGroupConvo.get('lastJoinedTimestamp'); + const existingTimestampMs = legacyGroupConvo.getLastJoinedTimestamp(); const existingJoinedAtSeconds = Math.floor(existingTimestampMs / 1000); if (existingJoinedAtSeconds !== fromWrapper.joinedAtSeconds) { legacyGroupConvo.set({ @@ -581,7 +581,7 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) { // changes = true; // } // start polling for this group if we haven't left it yet. The wrapper does not store this info for legacy group so we check from the DB entry instead - if (!legacyGroupConvo.get('isKickedFromGroup') && !legacyGroupConvo.get('left')) { + if (!legacyGroupConvo.isKickedFromGroup() && !legacyGroupConvo.isLeft()) { getSwarmPollingInstance().addGroupId(PubKey.cast(fromWrapper.pubkeyHex)); // save the encryption keypair if needed diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index df4a41e31..21063d130 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -695,7 +695,7 @@ async function handleMessageRequestResponse( unblindedConvoId, ConversationTypeEnum.PRIVATE ); - let mostRecentActiveAt = Math.max(...compact(convosToMerge.map(m => m.get('active_at')))); + let mostRecentActiveAt = Math.max(...compact(convosToMerge.map(m => m.getActiveAt()))); if (!isFinite(mostRecentActiveAt) || mostRecentActiveAt <= 0) { mostRecentActiveAt = toNumber(envelope.timestamp); } @@ -710,11 +710,11 @@ async function handleMessageRequestResponse( if (convosToMerge.length) { // merge fields we care by hand conversationToApprove.set({ - profileKey: convosToMerge[0].get('profileKey'), - displayNameInProfile: convosToMerge[0].get('displayNameInProfile'), + profileKey: convosToMerge[0].getProfileKey(), + displayNameInProfile: convosToMerge[0].getRealSessionUsername(), avatarInProfile: convosToMerge[0].get('avatarInProfile'), - avatarPointer: convosToMerge[0].get('avatarPointer'), // don't set the avatar pointer + avatarPointer: convosToMerge[0].getAvatarPointer(), // don't set the avatar pointer // nickname might be set already in conversationToApprove, so don't overwrite it }); diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 0f9f62716..8f9267154 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -312,7 +312,7 @@ async function handleRegularMessage( } } - const conversationActiveAt = conversation.get('active_at'); + const conversationActiveAt = conversation.getActiveAt(); if ( !conversationActiveAt || conversation.isHidden() || @@ -422,7 +422,7 @@ export async function handleMessageJob( // to their source message. conversation.set({ - active_at: Math.max(conversation.get('active_at'), messageModel.get('sent_at') || 0), + active_at: Math.max(conversation.getActiveAt() || 0, messageModel.get('sent_at') || 0), }); // this is a throttled call and will only run once every 1 sec at most conversation.updateLastMessage(); diff --git a/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts b/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts index e52087a45..9bbec74ec 100644 --- a/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts +++ b/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts @@ -92,7 +92,7 @@ export async function sogsV3FetchPreviewAndSaveIt(roomInfos: OpenGroupV2RoomWith if (!convo) { return; } - let existingImageId = convo.get('avatarImageId'); + let existingImageId = convo.getAvatarImageId(); if (existingImageId === imageIdNumber) { // return early as the imageID about to be downloaded the one already set as avatar is the same. return; @@ -117,7 +117,7 @@ export async function sogsV3FetchPreviewAndSaveIt(roomInfos: OpenGroupV2RoomWith if (!convo) { return; } - existingImageId = convo.get('avatarImageId'); + existingImageId = convo.getAvatarImageId(); if (existingImageId !== imageIdNumber && isFinite(imageIdNumber)) { // we have to trigger an update // write the file to the disk (automatically encrypted), diff --git a/ts/session/apis/snode_api/swarmPolling.ts b/ts/session/apis/snode_api/swarmPolling.ts index d29c713c7..7d15ae720 100644 --- a/ts/session/apis/snode_api/swarmPolling.ts +++ b/ts/session/apis/snode_api/swarmPolling.ts @@ -143,7 +143,7 @@ export class SwarmPolling { if (!convo) { return SWARM_POLLING_TIMEOUT.INACTIVE; } - const activeAt = convo.get('active_at'); + const activeAt = convo.getActiveAt(); if (!activeAt) { return SWARM_POLLING_TIMEOUT.INACTIVE; } @@ -437,10 +437,10 @@ export class SwarmPolling { const closedGroupsOnly = convos.filter( (c: ConversationModel) => - c.isClosedGroup() && !c.isBlocked() && !c.get('isKickedFromGroup') && !c.get('left') + c.isClosedGroup() && !c.isBlocked() && !c.isKickedFromGroup() && !c.isLeft() ); - closedGroupsOnly.forEach((c: any) => { + closedGroupsOnly.forEach((c) => { this.addGroupId(new PubKey(c.id)); }); } diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index cca58fae7..617d9b67b 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -473,7 +473,7 @@ async function leaveClosedGroup(groupId: string, fromSyncMessage: boolean) { } else { // otherwise, just the exclude ourself from the members and trigger an update with this convo.set({ left: true }); - members = (convo.get('members') || []).filter((m: string) => m !== ourNumber); + members = (convo.getGroupMembers() || []).filter((m: string) => m !== ourNumber); admins = convo.getGroupAdmins(); } convo.set({ members }); diff --git a/ts/session/group/closed-group.ts b/ts/session/group/closed-group.ts index 543209fb4..846b19ca1 100644 --- a/ts/session/group/closed-group.ts +++ b/ts/session/group/closed-group.ts @@ -73,7 +73,7 @@ export async function initiateClosedGroupUpdate( name: groupName, members, // remove from the zombies list the zombies not which are not in the group anymore - zombies: convo.get('zombies')?.filter(z => members.includes(z)), + zombies: convo.getGroupZombies()?.filter(z => members.includes(z)), activeAt: Date.now(), expireTimer: convo.get('expireTimer'), }; @@ -180,12 +180,12 @@ export async function addUpdateMessage( function buildGroupDiff(convo: ConversationModel, update: GroupInfo): GroupDiff { const groupDiff: GroupDiff = {}; - if (convo.get('displayNameInProfile') !== update.name) { + if (convo.getRealSessionUsername() !== update.name) { groupDiff.newName = update.name; } - const oldMembers = convo.get('members'); - const oldZombies = convo.get('zombies'); + const oldMembers = convo.getGroupMembers(); + const oldZombies = convo.getGroupZombies(); const oldMembersWithZombies = _.uniq(oldMembers.concat(oldZombies)); const newMembersWithZombiesLeft = _.uniq(update.members.concat(update.zombies || [])); diff --git a/ts/session/group/open-group.ts b/ts/session/group/open-group.ts index 57ac05610..7f08c4f01 100644 --- a/ts/session/group/open-group.ts +++ b/ts/session/group/open-group.ts @@ -68,7 +68,7 @@ export async function initiateOpenGroupUpdate( contentType: MIME.IMAGE_UNKNOWN, // contentType is mostly used to generate previews and screenshot. We do not care for those in this case. }); await convo.setSessionProfile({ - displayName: groupName || convo.get('displayNameInProfile') || window.i18n('unknown'), + displayName: groupName || convo.getRealSessionUsername() || window.i18n('unknown'), avatarPath: upgraded.path, avatarImageId, }); diff --git a/ts/session/profile_manager/ProfileManager.ts b/ts/session/profile_manager/ProfileManager.ts index c43fae9fc..77bddc95d 100644 --- a/ts/session/profile_manager/ProfileManager.ts +++ b/ts/session/profile_manager/ProfileManager.ts @@ -21,7 +21,7 @@ async function updateOurProfileSync( } await updateProfileOfContact(us, displayName, profileUrl, profileKey); - if (priority !== null && ourConvo.get('priority') !== priority) { + if (priority !== null && ourConvo.getPriority() !== priority) { ourConvo.set('priority', priority); await ourConvo.commit(); } @@ -43,7 +43,7 @@ async function updateProfileOfContact( return; } let changes = false; - const existingDisplayName = conversation.get('displayNameInProfile'); + const existingDisplayName = conversation.getRealSessionUsername(); // avoid setting the display name to an invalid value if (existingDisplayName !== displayName && !isEmpty(displayName)) { @@ -55,8 +55,8 @@ async function updateProfileOfContact( let avatarChanged = false; // trust whatever we get as an update. It either comes from a shared config wrapper or one of that user's message. But in any case we should trust it, even if it gets resetted. - const prevPointer = conversation.get('avatarPointer'); - const prevProfileKey = conversation.get('profileKey'); + const prevPointer = conversation.getAvatarPointer(); + const prevProfileKey = conversation.getProfileKey(); // we have to set it right away and not in the async download job, as the next .commit will save it to the // database and wrapper (and we do not want to override anything in the wrapper's content diff --git a/ts/session/utils/User.ts b/ts/session/utils/User.ts index 0bcae2c78..51c591291 100644 --- a/ts/session/utils/User.ts +++ b/ts/session/utils/User.ts @@ -103,10 +103,10 @@ export function getOurProfile(): LokiProfile | undefined { // in their primary device's conversation const ourNumber = Storage.get('primaryDevicePubKey') as string; const ourConversation = getConversationController().get(ourNumber); - const ourProfileKeyHex = ourConversation.get('profileKey'); + const ourProfileKeyHex = ourConversation.getProfileKey(); const profileKeyAsBytes = ourProfileKeyHex ? fromHexToArray(ourProfileKeyHex) : null; - const avatarPointer = ourConversation.get('avatarPointer'); + const avatarPointer = ourConversation.getAvatarPointer(); const displayName = ourConversation.getRealSessionUsername() || 'Anonymous'; return { displayName, diff --git a/ts/session/utils/calling/CallManager.ts b/ts/session/utils/calling/CallManager.ts index 840d88aa1..d06ee5407 100644 --- a/ts/session/utils/calling/CallManager.ts +++ b/ts/session/utils/calling/CallManager.ts @@ -1144,7 +1144,7 @@ export async function handleCallTypeOffer( // show a notification const callerConvo = getConversationController().get(sender); - const convNotif = callerConvo?.get('triggerNotificationsFor') || 'disabled'; + const convNotif = callerConvo?.getNotificationsFor() || 'disabled'; if (convNotif === 'disabled') { window?.log?.info('notifications disabled for convo', ed25519Str(sender)); } else if (callerConvo) { diff --git a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts index 273ab4346..5f81e2887 100644 --- a/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts +++ b/ts/session/utils/job_runners/jobs/AvatarDownloadJob.ts @@ -35,8 +35,8 @@ export function shouldAddAvatarDownloadJob({ conversationId }: { conversationId: window.log.warn('shouldAddAvatarDownloadJob can only be used for private convos currently'); return false; } - const prevPointer = conversation.get('avatarPointer'); - const profileKey = conversation.get('profileKey'); + const prevPointer = conversation.getAvatarPointer(); + const profileKey = conversation.getProfileKey(); const hasNoAvatar = isEmpty(prevPointer) || isEmpty(profileKey); if (hasNoAvatar) { @@ -116,8 +116,8 @@ class AvatarDownloadJob extends PersistedJob { return RunJobResult.PermanentFailure; } let changes = false; - const toDownloadPointer = conversation.get('avatarPointer'); - const toDownloadProfileKey = conversation.get('profileKey'); + const toDownloadPointer = conversation.getAvatarPointer(); + const toDownloadProfileKey = conversation.getProfileKey(); // if there is an avatar and profileKey for that user ('', null and undefined excluded), download, decrypt and save the avatar locally. if (toDownloadPointer && toDownloadProfileKey) { diff --git a/ts/session/utils/libsession/libsession_utils_contacts.ts b/ts/session/utils/libsession/libsession_utils_contacts.ts index db45b1bdb..21788247d 100644 --- a/ts/session/utils/libsession/libsession_utils_contacts.ts +++ b/ts/session/utils/libsession/libsession_utils_contacts.ts @@ -49,12 +49,12 @@ async function insertContactFromDBIntoWrapperAndRefresh(id: string): Promise> => { // Filter open groups v2 const openGroupsV2ConvoIds = convos - .filter(c => !!c.get('active_at') && c.isOpenGroupV2() && !c.get('left')) + .filter(c => !!c.getActiveAt() && c.isOpenGroupV2() && !c.isLeft()) .map(c => c.id) as Array; const urls = await Promise.all( @@ -161,13 +161,13 @@ const getValidClosedGroups = async (convos: Array) => { // Filter Closed/Medium groups const closedGroupModels = convos.filter( c => - !!c.get('active_at') && + !!c.getActiveAt() && c.isClosedGroup() && - c.get('members')?.includes(ourPubKey) && - !c.get('left') && - !c.get('isKickedFromGroup') && + c.getGroupMembers()?.includes(ourPubKey) && + !c.isLeft() && + !c.isKickedFromGroup() && !c.isBlocked() && - c.get('displayNameInProfile') + c.getRealSessionUsername() ); const closedGroups = await Promise.all( @@ -180,8 +180,8 @@ const getValidClosedGroups = async (convos: Array) => { return new ConfigurationMessageClosedGroup({ publicKey: groupPubKey, - name: c.get('displayNameInProfile') || '', - members: c.get('members') || [], + name: c.getRealSessionUsername() || '', + members: c.getGroupMembers() || [], admins: c.getGroupAdmins(), encryptionKeyPair: ECKeyPair.fromHexKeyPair(fetchEncryptionKeyPair), }); @@ -199,7 +199,7 @@ const getValidContacts = (convos: Array) => { // blindedId are synced with the outbox logic. const contactsModels = convos.filter( c => - !!c.get('active_at') && + !!c.getActiveAt() && c.getRealSessionUsername() && c.isPrivate() && c.isApproved() && @@ -208,7 +208,7 @@ const getValidContacts = (convos: Array) => { const contacts = contactsModels.map(c => { try { - const profileKey = c.get('profileKey'); + const profileKey = c.getProfileKey(); let profileKeyForContact = null; if (typeof profileKey === 'string') { // this will throw if the profileKey is not in hex. @@ -237,7 +237,7 @@ const getValidContacts = (convos: Array) => { return new ConfigurationMessageContact({ publicKey: c.id as string, displayName: c.getRealSessionUsername() || 'Anonymous', - profilePictureURL: c.get('avatarPointer'), + profilePictureURL: c.getAvatarPointer(), profileKey: !profileKeyForContact?.length ? undefined : profileKeyForContact, isApproved: c.isApproved(), isBlocked: c.isBlocked(), @@ -268,10 +268,10 @@ export const getCurrentConfigurationMessage = async ( const ourProfileKeyHex = getConversationController() .get(UserUtils.getOurPubKeyStrFromCache()) - ?.get('profileKey') || null; + ?.getProfileKey() || null; const profileKey = ourProfileKeyHex ? fromHexToArray(ourProfileKeyHex) : undefined; - const profilePicture = ourConvo?.get('avatarPointer') || undefined; + const profilePicture = ourConvo?.getAvatarPointer() || undefined; const displayName = ourConvo?.getRealSessionUsername() || 'Anonymous'; // this should never be undefined, but well... const activeOpenGroups = [...opengroupV2CompleteUrls];