diff --git a/ts/components/conversation/SessionRightPanel.tsx b/ts/components/conversation/SessionRightPanel.tsx index 3e48cb468..543366a40 100644 --- a/ts/components/conversation/SessionRightPanel.tsx +++ b/ts/components/conversation/SessionRightPanel.tsx @@ -281,7 +281,7 @@ export const SessionRightPanelWithDetails = () => { const deleteConvoAction = isPublic ? () => { - deleteAllMessagesByConvoIdWithConfirmation(selectedConvoKey); // TODO this does not delete the public group and showLeaveGroupByConvoId is not only working for closed groups + deleteAllMessagesByConvoIdWithConfirmation(selectedConvoKey); // TODOLATER this does not delete the public group and showLeaveGroupByConvoId is not only working for closed groups } : () => { showLeaveGroupByConvoId(selectedConvoKey); diff --git a/ts/components/conversation/message/message-item/ReadableMessage.tsx b/ts/components/conversation/message/message-item/ReadableMessage.tsx index e6241c70b..848d1c2ed 100644 --- a/ts/components/conversation/message/message-item/ReadableMessage.tsx +++ b/ts/components/conversation/message/message-item/ReadableMessage.tsx @@ -98,14 +98,17 @@ export const ReadableMessage = (props: ReadableMessageProps) => { const onVisible = useCallback( // tslint:disable-next-line: cyclomatic-complexity async (inView: boolean | Object) => { + if (!selectedConversationKey) { + return; + } // we are the most recent message - if (mostRecentMessageId === messageId && selectedConversationKey) { + if (mostRecentMessageId === messageId) { // make sure the app is focused, because we mark message as read here if (inView === true && isAppFocused) { dispatch(showScrollToBottomButton(false)); getConversationController() .get(selectedConversationKey) - ?.markConversationRead(receivedAt || 0); // TODO this should be `sentAt || serverTimestamp` I believe? + ?.markConversationRead(receivedAt || 0); // TODOLATER this should be `sentAt || serverTimestamp` I think dispatch(markConversationFullyRead(selectedConversationKey)); } else if (inView === false) { @@ -117,8 +120,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => { inView === true && isAppFocused && oldestMessageId === messageId && - !fetchingMoreInProgress && - selectedConversationKey + !fetchingMoreInProgress ) { debouncedTriggerLoadMoreTop(selectedConversationKey, oldestMessageId); } @@ -127,8 +129,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => { inView === true && isAppFocused && youngestMessageId === messageId && - !fetchingMoreInProgress && - selectedConversationKey + !fetchingMoreInProgress ) { debouncedTriggerLoadMoreBottom(selectedConversationKey, youngestMessageId); } @@ -140,7 +141,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => { isAppFocused ) { if (isUnread) { - // TODO this is pretty expensive and should instead use values from the redux store + // TODOLATER this is pretty expensive and should instead use values from the redux store const found = await Data.getMessageById(messageId); if (found && Boolean(found.get('unread'))) { @@ -149,7 +150,7 @@ export const ReadableMessage = (props: ReadableMessageProps) => { // this would be part of an redesign of the sending pipeline // mark the whole conversation as read until this point. // this will trigger the expire timer. - if (selectedConversationKey && foundSentAt) { + if (foundSentAt) { getConversationController() .get(selectedConversationKey) ?.markConversationRead(foundSentAt, Date.now()); diff --git a/ts/components/conversation/message/reactions/Reaction.tsx b/ts/components/conversation/message/reactions/Reaction.tsx index 146eae004..5f598881e 100644 --- a/ts/components/conversation/message/reactions/Reaction.tsx +++ b/ts/components/conversation/message/reactions/Reaction.tsx @@ -76,7 +76,7 @@ export const Reaction = (props: ReactionProps): ReactElement => { const reactionRef = useRef(null); const { docX, elW } = useMouse(reactionRef); - const gutterWidth = 380; // TODO make this a variable which can be shared in CSS and JS + const gutterWidth = 380; // TODOLATER make this a variable which can be shared in CSS and JS const tooltipMidPoint = POPUP_WIDTH / 2; // px const [tooltipPosition, setTooltipPosition] = useState('center'); diff --git a/ts/components/leftpane/ActionsPanel.tsx b/ts/components/leftpane/ActionsPanel.tsx index 4b6136673..fee386e3d 100644 --- a/ts/components/leftpane/ActionsPanel.tsx +++ b/ts/components/leftpane/ActionsPanel.tsx @@ -201,7 +201,7 @@ const doAppStartUp = async () => { void getSwarmPollingInstance().start(); void loadDefaultRooms(); - // TODO make this a job of the JobRunner + // TODOLATER make this a job of the JobRunner debounce(triggerAvatarReUploadIfNeeded, 200); /* Postpone a little bit of the polling of sogs messages to let the swarm messages come in first. */ diff --git a/ts/mains/main_renderer.tsx b/ts/mains/main_renderer.tsx index a66573cc5..f7a553aaf 100644 --- a/ts/mains/main_renderer.tsx +++ b/ts/mains/main_renderer.tsx @@ -193,7 +193,7 @@ Storage.onready(async () => { await LibSessionUtil.initializeLibSessionUtilWrappers(); } catch (e) { window.log.warn('LibSessionUtil.initializeLibSessionUtilWrappers failed with', e.message); - // TODO what should we do if this happens? + // I don't think there is anything we can do if this happens throw e; } } @@ -209,7 +209,7 @@ Storage.onready(async () => { ]); } catch (error) { window.log.error( - 'main_start.js: ConversationController failed to load:', + 'main_renderer: ConversationController failed to load:', error && error.stack ? error.stack : error ); } finally { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index e63ecf58a..75c136521 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -119,12 +119,11 @@ type InMemoryConvoInfos = { unreadCount: number; }; -// TODO decide it it makes sense to move this to a redux slice? /** * Some fields are not stored in the database, but are kept in memory. * We use this map to keep track of them. The key is the conversation id. */ -const inMemoryConvoInfos: Map = new Map(); +const inMemoryConvoInfos: Map = new Map(); // decide it it makes sense to move this to a redux slice? export class ConversationModel extends Backbone.Model { public updateLastMessage: () => any; @@ -339,6 +338,7 @@ export class ConversationModel extends Backbone.Model { const foundLegacyGroup = SessionUtilUserGroups.getLegacyGroupCached(this.id); const foundVolatileInfo = SessionUtilConvoInfoVolatile.getVolatileInfoCached(this.id); + // rely on the wrapper values rather than the DB ones if they exist in the wrapper if (foundContact) { if (foundContact.name) { toRet.displayNameInProfile = foundContact.name; @@ -363,10 +363,12 @@ export class ConversationModel extends Backbone.Model { toRet.isHidden = foundContact.hidden; if (foundContact.priority > 0) { - toRet.isPinned = true; // TODO priority also handles sorting + toRet.isPinned = true; } - // TODO expire timer (not in wrapper yet) + if (foundContact.expirationTimerSeconds > 0) { + toRet.expireTimer = foundContact.expirationTimerSeconds; + } } else { if (this.get('displayNameInProfile')) { toRet.displayNameInProfile = this.get('displayNameInProfile'); @@ -394,6 +396,10 @@ export class ConversationModel extends Backbone.Model { if (this.get('isPinned')) { toRet.isPinned = true; } + + if (this.get('expireTimer')) { + toRet.expireTimer = this.get('expireTimer'); + } } if (foundLegacyGroup) { @@ -412,7 +418,7 @@ export class ConversationModel extends Backbone.Model { if (foundCommunity) { if (foundCommunity.priority > 0) { - toRet.isPinned = true; // TODO priority also handles sorting + toRet.isPinned = true; } } @@ -887,7 +893,7 @@ export class ConversationModel extends Backbone.Model { */ public async addIncomingApprovalMessage(timestamp: number, source: string) { await this.addSingleIncomingMessage({ - sent_at: timestamp, // TODO: maybe add timestamp to messageRequestResponse? confirm it doesn't exist first + sent_at: timestamp, source, messageRequestResponse: { isApproved: 1, @@ -1210,7 +1216,7 @@ export class ConversationModel extends Backbone.Model { messageAttributes: Omit ) { // if there's a message by the other user, they've replied to us which we consider an accepted convo - if (!this.didApproveMe() && this.isPrivate()) { + if (this.isPrivate()) { await this.setDidApproveMe(true); } @@ -2177,7 +2183,7 @@ export async function commitConversationAndRefreshWrapper(id: string) { return; } // write to DB - // TODO remove duplicates between db and wrapper (except nickname&name as we need them for search) + // TODOLATER remove duplicates between db and wrapper (except nickname&name as we need them for search, or move search to wrapper too) // TODO when deleting a contact from the ConversationController, we still need to keep it in the wrapper but mark it as hidden (and we might need to add an hidden convo model field for it) const savedDetails = await Data.saveConversation(convo.attributes); diff --git a/ts/models/conversationAttributes.ts b/ts/models/conversationAttributes.ts index 451d026b5..ab7b94215 100644 --- a/ts/models/conversationAttributes.ts +++ b/ts/models/conversationAttributes.ts @@ -53,7 +53,7 @@ export interface ConversationAttributes { type: ConversationTypeEnum.PRIVATE | ConversationTypeEnum.GROUPV3 | ConversationTypeEnum.GROUP; // 0 means inactive (undefined and null too but we try to get rid of them and only have 0 = inactive) - active_at: number; + active_at: number; // this field is the one used to sort conversations in the left pane from most recent lastMessageStatus: LastMessageStatusType; /** @@ -64,10 +64,10 @@ export interface ConversationAttributes { */ lastMessage: string | null; - avatarImageId?: number; // SOGS ONLY: avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar + avatarImageId?: number; // avatar imageID is currently used only for sogs. It's the fileID of the image uploaded and set as the sogs avatar (not only sogs I think, but our profile too?) - left: boolean; // GROUPS ONLY: if we left the group (communities are removed right away so it not relevant to communities) - isKickedFromGroup: boolean; // GROUPS ONLY: if we got kicked from the group (communities just stop polling and a message sent get rejected, so not relevant to communities) + left: boolean; // LEGACY GROUPS ONLY: if we left the group (communities are removed right away so it not relevant to communities) // TODOLATER to remove after legacy closed group are dropped + isKickedFromGroup: boolean; // LEGACY GROUPS ONLY: if we got kicked from the group (communities just stop polling and a message sent get rejected, so not relevant to communities) // TODOLATER to remove after legacy closed group are dropped avatarInProfile?: string; // this is the avatar path locally once downloaded and stored in the application attachments folder @@ -75,9 +75,9 @@ export interface ConversationAttributes { conversationIdOrigin?: string; // Blinded message requests ONLY: The community from which this conversation originated from - // TODO those two items are only used for legacy closed groups and will be removed when we get rid of the legacy closed groups support - lastJoinedTimestamp: number; // ClosedGroup: last time we were added to this group // TODO to remove after legacy closed group are dropped - zombies: Array; // only used for closed groups. Zombies are users which left but not yet removed by the admin // TODO to remove after legacy closed group are dropped + // TODOLATER those two items are only used for legacy closed groups and will be removed when we get rid of the legacy closed groups support + lastJoinedTimestamp: number; // ClosedGroup: last time we were added to this group // TODOLATER to remove after legacy closed group are dropped + zombies: Array; // only used for closed groups. Zombies are users which left but not yet removed by the admin // TODOLATER to remove after legacy closed group are dropped // =========================================================================== // All of the items below are duplicated one way or the other with libsession. diff --git a/ts/node/migration/sessionMigrations.ts b/ts/node/migration/sessionMigrations.ts index 29ded3106..1c099db25 100644 --- a/ts/node/migration/sessionMigrations.ts +++ b/ts/node/migration/sessionMigrations.ts @@ -1218,6 +1218,7 @@ function insertContactIntoContactWrapper( const dbBlocked = blockedNumbers.includes(contact.id); const hidden = contact.hidden || false; const isPinned = contact.isPinned; + const expirationTimerSeconds = contact.expireTimer || 0; const wrapperContact = getContactInfoFromDBValues({ id: contact.id, @@ -1230,6 +1231,7 @@ function insertContactIntoContactWrapper( dbProfileUrl: contact.avatarPointer || undefined, isPinned, hidden, + expirationTimerSeconds, }); try { @@ -1254,6 +1256,7 @@ function insertContactIntoContactWrapper( dbProfileUrl: undefined, isPinned: false, hidden, + expirationTimerSeconds: 0, }) ); } catch (e) { @@ -1770,9 +1773,7 @@ function updateToSessionSchemaVersion30(currentVersion: number, db: BetterSqlite data: convoVolatileDump, }); - // TODO we've just created the initial dumps. We have to add an initial SyncJob to the database so it is run on the next app start/ - // or find another way of adding one on the next start (store an another item in the DB and check for it on app start?) - // or just start a conf sync job on app start + // we've just created the initial dumps. A ConfSyncJob is run when the app starts after 20 seconds } catch (e) { console.error(`failed to create initial wrapper: `, e.stack); // if we get an exception here, most likely no users are logged in yet. We can just continue the transaction and the wrappers will be created when a user creates a new account. diff --git a/ts/node/sql.ts b/ts/node/sql.ts index 7270dc543..d12ef88e6 100644 --- a/ts/node/sql.ts +++ b/ts/node/sql.ts @@ -504,7 +504,7 @@ function fetchConvoMemoryDetails(convoId: string): SaveConversationReturn { const unreadCount = getUnreadCountByConversation(convoId); const lastReadTimestampMessageSentTimestamp = getLastMessageReadInConversation(convoId); - // TODO it would be nice to be able to remove the lastMessage and lastMessageStatus from the conversation table, and just return it when saving the conversation + // TODOLATER it would be nice to be able to remove the lastMessage and lastMessageStatus from the conversation table, and just return it when saving the conversation // and saving it in memory only. // But we'd need to update a bunch of things as we do some logic before setting the lastUpdate text and status mostly in `getMessagePropStatus` and `getNotificationText()` // const lastMessages = getLastMessagesByConversation(convoId, 1) as Array:Record>; @@ -557,7 +557,7 @@ export function getIdentityKeys(db: BetterSqlite3.Database) { const ed25519PrivateKeyUintArray = parsedIdentityKey?.value?.ed25519KeyPair?.privateKey; - // TODO migrate the ed25519KeyPair for all the users already logged in to a base64 representation + // TODOLATER migrate the ed25519KeyPair for all the users already logged in to a base64 representation const privateEd25519 = new Uint8Array(Object.values(ed25519PrivateKeyUintArray)); if (!privateEd25519 || isEmpty(privateEd25519)) { @@ -1404,11 +1404,11 @@ function getFirstUnreadMessageWithMention( } const likeMatch = `%@${ourPkInThatConversation}%`; - // TODO make this use the fts search table rather than this one? + // TODOLATER make this use the fts search table rather than this one? const rows = assertGlobalInstanceOrInstance(instance) .prepare( ` - SELECT id, json FROM ${MESSAGES_TABLE} WHERE + SELECT id FROM ${MESSAGES_TABLE} WHERE conversationId = $conversationId AND unread = $unread AND body LIKE $likeMatch diff --git a/ts/receiver/configMessage.ts b/ts/receiver/configMessage.ts index 739226bb1..70fcaaabc 100644 --- a/ts/receiver/configMessage.ts +++ b/ts/receiver/configMessage.ts @@ -366,7 +366,7 @@ async function handleLegacyGroupUpdate(latestEnvelopeTimestamp: number) { legacyGroupConvo.get('active_at') < latestEnvelopeTimestamp ? legacyGroupConvo.get('active_at') : latestEnvelopeTimestamp, - weWereJustAdded: false, // TODO to remove + weWereJustAdded: false, // TODOLATER to remove }; await ClosedGroup.updateOrCreateClosedGroup(groupDetails); @@ -473,10 +473,9 @@ async function applyConvoVolatileUpdateFromWrapper( async function handleConvoInfoVolatileUpdate( result: IncomingConfResult ): Promise { - // TODO do we want to enforce this? - // if (!result.needsDump) { - // return result; - // } + if (!result.needsDump) { + return result; + } const types = SessionUtilConvoInfoVolatile.getConvoInfoVolatileTypes(); for (let typeIndex = 0; typeIndex < types.length; typeIndex++) { @@ -619,7 +618,6 @@ async function processMergingResults(results: Map> ) { - // TODO: Remove this once `useSharedUtilForUserConfig` is permanent if (!window.sessionFeatureFlags.useSharedUtilForUserConfig) { return; } @@ -769,11 +767,9 @@ const handleClosedGroupsFromConfigLegacy = async ( publicKey: c.publicKey, }); try { - // TODO we should not drop the envelope from cache as long as we are still handling a new closed group from that same envelope - // check the removeFromCache inside handleNewClosedGroup() await handleNewClosedGroup(envelope, groupUpdate); } catch (e) { - window?.log?.warn('failed to handle a new closed group from configuration message'); + window?.log?.warn('failed to handle a new closed group from configuration message'); } }) ); diff --git a/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts b/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts index 88ab70963..cd36b82b9 100644 --- a/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts +++ b/ts/session/apis/open_group_api/sogsv3/sogsV3FetchFile.ts @@ -118,7 +118,7 @@ export async function sogsV3FetchPreviewAndSaveIt(roomInfos: OpenGroupV2RoomWith return; } existingImageId = convo.get('avatarImageId'); - if (existingImageId !== imageIdNumber && imageIdNumber) { + 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/SNodeAPI.ts b/ts/session/apis/snode_api/SNodeAPI.ts index 0a8559eec..aed7acc4a 100644 --- a/ts/session/apis/snode_api/SNodeAPI.ts +++ b/ts/session/apis/snode_api/SNodeAPI.ts @@ -13,7 +13,7 @@ export const ERROR_CODE_NO_CONNECT = 'ENETUNREACH: No network connection.'; // tslint:disable: max-func-body-length -// TODO we should merge those two functions together as they are almost exactly the same +// TODOLATER we should merge those two functions together as they are almost exactly the same const forceNetworkDeletion = async (): Promise | null> => { const sodium = await getSodiumRenderer(); const userX25519PublicKey = UserUtils.getOurPubKeyStrFromCache(); diff --git a/ts/session/conversations/ConversationController.ts b/ts/session/conversations/ConversationController.ts index 44d5dfa65..7f9925046 100644 --- a/ts/session/conversations/ConversationController.ts +++ b/ts/session/conversations/ConversationController.ts @@ -15,6 +15,8 @@ import { SessionUtilContact } from '../utils/libsession/libsession_utils_contact import { SessionUtilConvoInfoVolatile } from '../utils/libsession/libsession_utils_convo_info_volatile'; import { SessionUtilUserGroups } from '../utils/libsession/libsession_utils_user_groups'; import { ConfigurationDumpSync } from '../utils/job_runners/jobs/ConfigurationSyncDumpJob'; +import { LibSessionUtil } from '../utils/libsession/libsession_utils'; +import { assertUnreachable } from '../../types/sqlSharedTypes'; let instance: ConversationController | null; @@ -251,11 +253,7 @@ export class ConversationController { // await conversation.setIsApproved(false, false); await conversation.commit(); // this updates the wrappers content to reflect the hidden state - // The note to self cannot be removed from the wrapper I suppose, as it must always be there - // TODO I think we want to mark the contacts as hidden instead of removing them, so maybe keep the volatile info too? - // if (!isUsFromCache(conversation.id)) { - // await SessionUtilConvoInfoVolatile.remove1o1(conversation.id); - // } + // We don't remove entries from the contacts wrapper, so better keep corresponding convo volatile info for now (it will be pruned if needed) // TODO the call above won't mark the conversation as hidden in the wrapper, it will just stop being updated (which is a bad thing) } @@ -308,40 +306,49 @@ export class ConversationController { this.conversations.add(convoModels); const start = Date.now(); - // TODO make this a switch so we take care of all wrappers and have compilation errors if we forgot to add one. - // also keep in mind that the convo volatile one need to run for each convo so it must be outside of a `else` + const numberOfVariants = LibSessionUtil.requiredUserVariants.length; for (let index = 0; index < convoModels.length; index++) { const convo = convoModels[index]; - if (SessionUtilContact.isContactToStoreInContactsWrapper(convo)) { - await SessionUtilContact.refreshMappedValue(convo.id, true); - } else if (SessionUtilUserGroups.isUserGroupToStoreInWrapper(convo)) { - await SessionUtilUserGroups.refreshCachedUserGroup(convo.id, true); - } - // we actually want to run the convo volatile check and fetch even if one of the cases above is already true - if (SessionUtilConvoInfoVolatile.isConvoToStoreInWrapper(convo)) { - await SessionUtilConvoInfoVolatile.refreshConvoVolatileCached( - convo.id, - Boolean(convo.isClosedGroup() && convo.id.startsWith('05')), - true - ); - - await convo.refreshInMemoryDetails(); + for (let wrapperIndex = 0; wrapperIndex < numberOfVariants; wrapperIndex++) { + const variant = LibSessionUtil.requiredUserVariants[wrapperIndex]; + + switch (variant) { + case 'UserConfig': + break; + case 'ContactsConfig': + if (SessionUtilContact.isContactToStoreInContactsWrapper(convo)) { + await SessionUtilContact.refreshMappedValue(convo.id, true); + } + break; + case 'UserGroupsConfig': + if (SessionUtilUserGroups.isUserGroupToStoreInWrapper(convo)) { + await SessionUtilUserGroups.refreshCachedUserGroup(convo.id, true); + } + break; + + case 'ConvoInfoVolatileConfig': + if (SessionUtilConvoInfoVolatile.isConvoToStoreInWrapper(convo)) { + await SessionUtilConvoInfoVolatile.refreshConvoVolatileCached( + convo.id, + Boolean(convo.isClosedGroup() && convo.id.startsWith('05')), + true + ); + + await convo.refreshInMemoryDetails(); + } + break; + + default: + assertUnreachable( + variant, + `ConversationController: load() unhandled case "${variant}"` + ); + } } } window.log.info(`refreshAllWrappersMappedValues took ${Date.now() - start}ms`); this._initialFetchComplete = true; - // TODO do we really need to do this? - // this.conversations.forEach((conversation: ConversationModel) => { - // if ( - // conversation.isActive() && - // !conversation.isHidden() && - // !conversation.get('lastMessage') - // ) { - // conversation.updateLastMessage(); - // } - // }); - window?.log?.info( `ConversationController: done with initial fetch in ${Date.now() - startLoad}ms.` ); diff --git a/ts/session/group/open-group.ts b/ts/session/group/open-group.ts index fe20d215d..8e69e5aa8 100644 --- a/ts/session/group/open-group.ts +++ b/ts/session/group/open-group.ts @@ -42,11 +42,11 @@ export async function initiateOpenGroupUpdate( return false; } try { - const { fileId, fileUrl } = uploadedFileDetails; + const { fileId: avatarImageId, fileUrl } = uploadedFileDetails; // this is kind of a hack just made to avoid having a specific function downloading from sogs by URL rather than fileID const downloaded = await downloadAttachmentSogsV3( - { id: fileId, size: null, url: fileUrl }, + { id: avatarImageId, size: null, url: fileUrl }, roomInfos ); @@ -67,11 +67,9 @@ export async function initiateOpenGroupUpdate( isRaw: true, contentType: MIME.IMAGE_UNKNOWN, // contentType is mostly used to generate previews and screenshot. We do not care for those in this case. }); - const avatarImageId = fileId; await convo.setSessionProfile({ displayName: groupName || convo.get('displayNameInProfile') || 'Unknown', avatarPath: upgraded.path, - avatarImageId, }); } catch (e) { diff --git a/ts/session/utils/AttachmentsDownload.ts b/ts/session/utils/AttachmentsDownload.ts index 15f1c2e29..68fdef277 100644 --- a/ts/session/utils/AttachmentsDownload.ts +++ b/ts/session/utils/AttachmentsDownload.ts @@ -28,7 +28,7 @@ let timeout: any; let logger: any; const _activeAttachmentDownloadJobs: any = {}; -// TODO type those `any` properties +// TODOLATER type those `any` properties export async function start(options: any = {}) { ({ logger } = options); diff --git a/ts/session/utils/job_runners/jobs/ConfigurationSyncDumpJob.ts b/ts/session/utils/job_runners/jobs/ConfigurationSyncDumpJob.ts index dd8f67c33..a4e9cf169 100644 --- a/ts/session/utils/job_runners/jobs/ConfigurationSyncDumpJob.ts +++ b/ts/session/utils/job_runners/jobs/ConfigurationSyncDumpJob.ts @@ -95,7 +95,7 @@ class ConfigurationSyncDumpJob extends PersistedJob = [ 'UserConfig', 'ContactsConfig', @@ -44,8 +43,7 @@ async function initializeLibSessionUtilWrappers() { throw new Error('edkeypair not found for current user'); } const privateKeyEd25519 = keypair.privKeyBytes; - // let's plan a sync on start for now - // TODO is this causing any issues? + // let's plan a sync on start with some room for the app to be ready setTimeout(() => ConfigurationSync.queueNewJobIfNeeded, 20000); // fetch the dumps we already have from the database diff --git a/ts/session/utils/libsession/libsession_utils_contacts.ts b/ts/session/utils/libsession/libsession_utils_contacts.ts index 5d668df62..9b495645f 100644 --- a/ts/session/utils/libsession/libsession_utils_contacts.ts +++ b/ts/session/utils/libsession/libsession_utils_contacts.ts @@ -83,6 +83,7 @@ async function insertContactFromDBIntoWrapperAndRefresh(id: string): Promise