From 197383a52f077cf6afd596171f58fd8736df42e1 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 19 Sep 2023 13:02:40 +1000 Subject: [PATCH] feat: move some the convomodel.get attributes to functions this is because we need to be able to override what is returned by what is in the redux lib slice if needed (libsession data overrides what is in the DB for groupv3) --- .../message/message-content/MessageAvatar.tsx | 2 +- ts/components/dialog/InviteContactsDialog.tsx | 4 +- .../dialog/UpdateGroupMembersDialog.tsx | 6 +- .../dialog/UpdateGroupNameDialog.tsx | 2 +- ts/interactions/conversationInteractions.ts | 14 +- ts/models/conversation.ts | 131 ++++++++++++++---- ts/models/message.ts | 2 +- ts/receiver/closedGroups.ts | 22 +-- ts/receiver/configMessage.ts | 14 +- ts/receiver/contentMessage.ts | 8 +- ts/receiver/queuedJob.ts | 4 +- .../open_group_api/sogsv3/sogsV3FetchFile.ts | 4 +- ts/session/apis/snode_api/swarmPolling.ts | 6 +- .../conversations/ConversationController.ts | 2 +- ts/session/group/closed-group.ts | 8 +- ts/session/group/open-group.ts | 2 +- ts/session/profile_manager/ProfileManager.ts | 8 +- ts/session/utils/User.ts | 4 +- ts/session/utils/calling/CallManager.ts | 2 +- .../job_runners/jobs/AvatarDownloadJob.ts | 8 +- .../libsession/libsession_utils_contacts.ts | 6 +- .../libsession_utils_user_groups.ts | 14 +- .../libsession_utils_user_profile.ts | 8 +- ts/session/utils/sync/syncUtils.ts | 26 ++-- 24 files changed, 191 insertions(+), 116 deletions(-) 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];