diff --git a/app/sql.js b/app/sql.js index b9ea7b239..ed9269a9a 100644 --- a/app/sql.js +++ b/app/sql.js @@ -59,6 +59,7 @@ module.exports = { removeMessage, getUnreadByConversation, getUnreadCountByConversation, + getIncomingMessagesCountByConversation, getMessageBySenderAndSentAt, getMessageBySenderAndServerTimestamp, getMessageBySenderAndTimestamp, @@ -2312,6 +2313,27 @@ function getUnreadCountByConversation(conversationId) { return row['count(*)']; } +function getIncomingMessagesCountByConversation(conversationId, type = '%') { + const row = globalInstance + .prepare( + `SELECT count(*) from ${MESSAGES_TABLE} + WHERE conversationId = $conversationId + AND type = $type;` + ) + .get({ + conversationId, + type, + }); + + if (!row) { + throw new Error( + `getIncomingMessagesCountByConversation: Unable to get incoming messages count of ${conversationId}` + ); + } + + return row['count(*)']; +} + // Note: Sorting here is necessary for getting the last message (with limit 1) // be sure to update the sorting order to sort messages on redux too (sortMessages) const orderByClause = 'ORDER BY COALESCE(serverTimestamp, sent_at, received_at) DESC'; @@ -2333,7 +2355,6 @@ function getMessagesByConversation(conversationId, { messageId = null, type = '% `WITH cte AS ( SELECT id, conversationId, json, row_number() OVER (${orderByClause}) as row_number FROM ${MESSAGES_TABLE} WHERE conversationId = $conversationId - AND type LIKE $type ), current AS ( SELECT row_number FROM cte diff --git a/ts/data/data.ts b/ts/data/data.ts index 1bee24d08..3476cd677 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -113,6 +113,7 @@ const channelsToMake = { _removeMessages, getUnreadByConversation, getUnreadCountByConversation, + getIncomingMessagesCountByConversation, removeAllMessagesInConversation, @@ -761,17 +762,19 @@ export async function getUnreadCountByConversation(conversationId: string): Prom return channels.getUnreadCountByConversation(conversationId); } +export async function getIncomingMessagesCountByConversation( + conversationId: string, + type: string = '%' +): Promise { + return channels.getIncomingMessagesCountByConversation(conversationId, type); +} + export async function getMessagesByConversation( conversationId: string, - { - type = '%', - skipTimerInit = false, - messageId = null, - }: { type?: string; skipTimerInit?: false; messageId: string | null } + { skipTimerInit = false, messageId = null }: { skipTimerInit?: false; messageId: string | null } ): Promise { const messages = await channels.getMessagesByConversation(conversationId, { messageId, - type, }); if (skipTimerInit) { for (const message of messages) { diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 9a09d6a42..c70337542 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -12,8 +12,8 @@ import { MessageModel } from './message'; import { MessageAttributesOptionals, MessageDirection } from './messageType'; import autoBind from 'auto-bind'; import { + getIncomingMessagesCountByConversation, getLastMessagesByConversation, - getMessagesByConversation, getUnreadByConversation, getUnreadCountByConversation, removeMessage as dataRemoveMessage, @@ -626,16 +626,14 @@ export class ConversationModel extends Backbone.Model { }; const shouldApprove = !this.isApproved() && this.isPrivate(); - const hasMsgsFromOther = - ( - await getMessagesByConversation(this.id, { - messageId: null, - type: MessageDirection.incoming, - }) - ).length > 0; + const incomingMessages = await getIncomingMessagesCountByConversation( + this.id, + MessageDirection.incoming + ); + const hasIncomingMessages = incomingMessages > 0; if (shouldApprove) { await this.setIsApproved(true); - if (!this.didApproveMe() && hasMsgsFromOther) { + if (!this.didApproveMe() && hasIncomingMessages) { await this.setDidApproveMe(true); await this.sendMessageRequestResponse(true); void forceSyncConfigurationNowIfNeeded(); @@ -1163,12 +1161,6 @@ export class ConversationModel extends Backbone.Model { isApproved: value, }); - if (!this.isApproved() && value) { - // if convo hasn't been approved until now, send approval msg - this.sendMessageRequestResponse(true); - void forceSyncConfigurationNowIfNeeded(); - } - if (shouldCommit) { await this.commit(); } @@ -1509,7 +1501,7 @@ export class ConversationModel extends Backbone.Model { } } - private async addSingleMessage(messageAttributes: MessageAttributesOptionals) { + public async addSingleMessage(messageAttributes: MessageAttributesOptionals) { const model = new MessageModel(messageAttributes); // no need to trigger a UI update now, we trigger a messagesAdded just below diff --git a/ts/receiver/contentMessage.ts b/ts/receiver/contentMessage.ts index 7a4b377d9..56b90cefd 100644 --- a/ts/receiver/contentMessage.ts +++ b/ts/receiver/contentMessage.ts @@ -19,6 +19,7 @@ import { getAllCachedECKeyPair } from './closedGroups'; import { handleCallMessage } from './callMessage'; import { SettingsKey } from '../data/settings-key'; import { ConversationTypeEnum } from '../models/conversation'; +import { showMessageRequestBanner } from '../state/ducks/userConfig'; export async function handleSwarmContentMessage(envelope: EnvelopePlus, messageHash: string) { try { @@ -370,6 +371,19 @@ export async function innerHandleSwarmContentMessage( ); } + const newConvo = await getConversationController().getOrCreateAndWait( + envelope.source, + ConversationTypeEnum.PRIVATE + ); + + if ( + newConvo.isPrivate() && + !newConvo.isApproved() && + window.inboxStore?.getState().userConfig.hideMessageRequests + ) { + window.inboxStore?.dispatch(showMessageRequestBanner()); + } + if (content.dataMessage) { if (content.dataMessage.profileKey && content.dataMessage.profileKey.length === 0) { content.dataMessage.profileKey = null; diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index 2e86b373f..0bab841cd 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -256,19 +256,6 @@ async function handleRegularMessage( await handleSyncedReceipts(message, conversation); } - if ( - conversation.isPrivate() && - !conversation.isApproved() && - window.inboxStore?.getState().userConfig.hideMessageRequests - ) { - window.inboxStore?.dispatch(showMessageRequestBanner()); - } - - if (!conversation.didApproveMe()) { - conversation.setDidApproveMe(true); - await forceSyncConfigurationNowIfNeeded(); - } - const conversationActiveAt = conversation.get('active_at'); if (!conversationActiveAt || (message.get('sent_at') || 0) > conversationActiveAt) { conversation.set({