diff --git a/electron_app/src/DBManager.js b/electron_app/src/DBManager.js index 448119938..35ffd5eba 100644 --- a/electron_app/src/DBManager.js +++ b/electron_app/src/DBManager.js @@ -100,6 +100,10 @@ const filterUniqueContacts = contacts => { return contactsUnique.contacts; }; +const getAllContacts = () => { + return db.select('name', 'email').from(Table.CONTACT); +}; + const getContactByEmails = (emails, trx) => { const knex = trx || db; return knex @@ -116,10 +120,6 @@ const getContactByIds = (ids, trx) => { .whereIn('id', ids); }; -const getAllContacts = () => { - return db.select('name', 'email').from(Table.CONTACT); -}; - const getContactsByEmailId = async emailId => { const emailContacts = await db .select('contactId', 'type') @@ -175,6 +175,23 @@ const createEmailLabel = async (emailLabels, trx) => { } }; +const deleteEmailLabel = ({ emailsId, labelIds }, trx) => { + const knex = trx || db; + return knex + .table(Table.EMAIL_LABEL) + .whereIn('labelId', labelIds) + .whereIn('emailId', emailsId) + .del(); +}; + +const deleteEmailLabelsByEmailId = (emailId, trx) => { + const knex = trx || db; + return knex + .table(Table.EMAIL_LABEL) + .where({ emailId }) + .del(); +}; + const filterEmailLabelIfNotStore = async (emailLabels, trx) => { const knex = trx || db; const emailIds = Array.from(new Set(emailLabels.map(item => item.emailId))); @@ -198,35 +215,18 @@ const filterEmailLabelIfNotStore = async (emailLabels, trx) => { .filter(item => item !== null); }; -const updateEmailLabel = ({ emailId, oldLabelId, newLabelId }) => { +const getEmailLabelsByEmailId = emailId => { return db + .select('labelId') .table(Table.EMAIL_LABEL) - .where({ emailId, labelId: oldLabelId }) - .update({ labelId: newLabelId }); -}; - -const deleteEmailLabel = ({ emailsId, labelIds }, trx) => { - const knex = trx || db; - return knex - .table(Table.EMAIL_LABEL) - .whereIn('labelId', labelIds) - .whereIn('emailId', emailsId) - .del(); -}; - -const deleteEmailLabelsByEmailId = (emailId, trx) => { - const knex = trx || db; - return knex - .table(Table.EMAIL_LABEL) - .where({ emailId }) - .del(); + .where({ emailId }); }; -const getEmailLabelsByEmailId = emailId => { +const updateEmailLabel = ({ emailId, oldLabelId, newLabelId }) => { return db - .select('labelId') .table(Table.EMAIL_LABEL) - .where({ emailId }); + .where({ emailId, labelId: oldLabelId }) + .update({ labelId: newLabelId }); }; /* Email @@ -308,6 +308,40 @@ const createEmail = async (params, trx) => { }); }; +const deleteEmailByKey = key => { + return db + .table(Table.EMAIL) + .where({ key }) + .del(); +}; + +const deleteEmailsByIds = (ids, trx) => { + const knex = trx || db; + return knex + .table(Table.EMAIL) + .whereIn('id', ids) + .del(); +}; + +const deleteEmailsByThreadId = threadIds => { + return db + .table(Table.EMAIL) + .whereIn('threadId', threadIds) + .del(); +}; + +const deleteEmailLabelAndContactByEmailId = (id, optionalEmailToSave) => { + return db.transaction(async trx => { + await deleteEmailsByIds([id], trx); + await deleteEmailContactByEmailId(id, trx); + await deleteEmailLabelsByEmailId(id, trx); + if (optionalEmailToSave) { + const [emailId] = await createEmail(optionalEmailToSave, trx); + return emailId; + } + }); +}; + const formEmailContact = ({ emailId, contactStored, contacts, type }) => { return contacts.map(contactToSearch => { const emailMatched = contactToSearch.match(/<(.*)>/); @@ -344,6 +378,25 @@ const getEmailByKey = key => { .where({ key }); }; +const getEmailsByKeys = keys => { + return db + .select('*') + .from(Table.EMAIL) + .whereIn('key', keys); +}; + +const getEmailsByLabelIds = labelIds => { + return db + .select(`${Table.EMAIL}.*`) + .from(Table.EMAIL) + .leftJoin( + Table.EMAIL_LABEL, + `${Table.EMAIL}.id`, + `${Table.EMAIL_LABEL}.emailId` + ) + .whereIn(`${Table.EMAIL_LABEL}.labelId`, labelIds); +}; + const getEmailsByThreadId = threadId => { return db .select( @@ -557,14 +610,6 @@ const partThreadQueryByMatchText = (query, text) => .orWhere('subject', 'like', `%${text}%`); }); -const deleteEmailsByIds = (ids, trx) => { - const knex = trx || db; - return knex - .table(Table.EMAIL) - .whereIn('id', ids) - .del(); -}; - const getEmailsUnredByLabelId = params => { const { labelId, rejectedLabelIds } = params; return db(`${Table.EMAIL}`) @@ -600,44 +645,6 @@ const getUnreadEmailsByThreadId = threadId => { .where({ threadId, unread: 1 }); }; -const deleteEmailByKey = key => { - return db - .table(Table.EMAIL) - .where({ key }) - .del(); -}; - -const deleteEmailsByThreadId = threadIds => { - return db - .table(Table.EMAIL) - .whereIn('threadId', threadIds) - .del(); -}; - -const deleteEmailLabelAndContactByEmailId = (id, optionalEmailToSave) => { - return db.transaction(async trx => { - await deleteEmailsByIds([id], trx); - await deleteEmailContactByEmailId(id, trx); - await deleteEmailLabelsByEmailId(id, trx); - if (optionalEmailToSave) { - const [emailId] = await createEmail(optionalEmailToSave, trx); - return emailId; - } - }); -}; - -const getEmailsByLabelIds = async labelIds => { - const emails = await db - .select('emailId') - .from(Table.EMAIL_LABEL) - .whereIn('labelId', labelIds); - const emailIds = emails.map(email => email.emailId); - return db - .select('*') - .table(Table.EMAIL) - .whereIn('id', emailIds); -}; - const updateEmail = ({ id, key, @@ -668,6 +675,16 @@ const updateEmail = ({ .update(params); }; +const updateEmails = ({ keys, unread }) => { + const params = noNulls({ + unread: typeof unread === 'boolean' ? unread : undefined + }); + return db + .table(Table.EMAIL) + .whereIn('key', keys) + .update(params); +}; + const updateEmailByThreadId = ({ threadId, unread }) => { const params = {}; if (typeof unread === 'boolean') params.unread = unread; @@ -683,6 +700,23 @@ const createLabel = params => { return db.table(Table.LABEL).insert(params); }; +const deleteLabelById = id => { + return db.transaction(async trx => { + const emailLabels = await trx + .select('*') + .from(Table.EMAIL_LABEL) + .where('labelId', id); + const emailsId = emailLabels.map(item => item.emailId); + if (emailsId.length) { + await deleteEmailLabel({ emailsId, labelId: id }, trx); + } + return trx + .table(Table.LABEL) + .where({ id }) + .del(); + }); +}; + const getAllLabels = () => { return db.select('*').from(Table.LABEL); }; @@ -719,23 +753,6 @@ const updateLabel = ({ id, color, text, visible }) => { .update(params); }; -const deleteLabelById = id => { - return db.transaction(async trx => { - const emailLabels = await trx - .select('*') - .from(Table.EMAIL_LABEL) - .where('labelId', id); - const emailsId = emailLabels.map(item => item.emailId); - if (emailsId.length) { - await deleteEmailLabel({ emailsId, labelId: id }, trx); - } - return trx - .table(Table.LABEL) - .where({ id }) - .del(); - }); -}; - /* File ----------------------------- */ const createFile = (files, trx) => { @@ -784,28 +801,29 @@ const getFileKeyByEmailId = emailId => { /* Feed Item ----------------------------- */ -const getAllFeedItems = () => { - return db.select('*').from(Table.FEEDITEM); -}; const createFeedItem = params => { return db.table(Table.FEEDITEM).insert(params); }; -const updateFeedItem = ({ id, seen }) => { - const params = {}; - if (seen) params.seen = seen; +const deleteFeedItemById = id => { return db .table(Table.FEEDITEM) .where({ id }) - .update(params); + .del(); }; -const deleteFeedItemById = id => { +const getAllFeedItems = () => { + return db.select('*').from(Table.FEEDITEM); +}; + +const updateFeedItem = ({ id, seen }) => { + const params = {}; + if (seen) params.seen = seen; return db .table(Table.FEEDITEM) .where({ id }) - .del(); + .update(params); }; /* PreKeyRecord @@ -814,13 +832,6 @@ const createPreKeyRecord = params => { return db.table(Table.PREKEYRECORD).insert(params); }; -const getPreKeyPair = params => { - return db - .select('preKeyPrivKey', 'preKeyPubKey') - .from(Table.PREKEYRECORD) - .where(params); -}; - const deletePreKeyPair = params => { return db .table(Table.PREKEYRECORD) @@ -828,6 +839,13 @@ const deletePreKeyPair = params => { .del(); }; +const getPreKeyPair = params => { + return db + .select('preKeyPrivKey', 'preKeyPubKey') + .from(Table.PREKEYRECORD) + .where(params); +}; + /* SignedPreKeyRecord ----------------------------- */ const createSignedPreKeyRecord = params => { @@ -885,6 +903,10 @@ const getSessionRecordByRecipientIds = recipientIds => { /* IdentityKeyRecord ----------------------------- */ +const createIdentityKeyRecord = params => { + return db.table(Table.IDENTITYKEYRECORD).insert(params); +}; + const getIdentityKeyRecord = params => { return db .select('identityKey') @@ -892,10 +914,6 @@ const getIdentityKeyRecord = params => { .where(params); }; -const createIdentityKeyRecord = params => { - return db.table(Table.IDENTITYKEYRECORD).insert(params); -}; - const updateIdentityKeyRecord = ({ recipientId, identityKey }) => { return db .table(Table.IDENTITYKEYRECORD) @@ -943,6 +961,7 @@ module.exports = { getContactsByEmailId, getEmailById, getEmailByKey, + getEmailsByKeys, getEmailsByLabelIds, getEmailsByThreadId, getEmailsCounterByLabelId, @@ -962,6 +981,7 @@ module.exports = { deleteLabelById, updateAccount, updateEmail, + updateEmails, updateEmailByThreadId, updateEmailLabel, updateFeedItem, diff --git a/electron_app/src/__integrations__/Email.integration.js b/electron_app/src/__integrations__/Email.integration.js index debb621c4..1a69157fb 100644 --- a/electron_app/src/__integrations__/Email.integration.js +++ b/electron_app/src/__integrations__/Email.integration.js @@ -138,7 +138,7 @@ describe('Update data email to Email Table:', () => { expect(isMuted).toBe(1); }); - it('should update email: unread', async () => { + it('should update email: unread by id', async () => { const id = 3; await DBManager.updateEmail({ id, @@ -148,6 +148,19 @@ describe('Update data email to Email Table:', () => { const unread = email.unread; expect(unread).toBe(0); }); + + it('should update emails: unread by keys', async () => { + const keys = ['keyC', 'keyId']; + await DBManager.updateEmails({ + keys, + unread: false + }); + const emails = await DBManager.getEmailsByKeys(keys); + const unreadEmailA = emails[0].unread; + const unreadEmailB = emails[1].unread; + expect(unreadEmailA).toBe(0); + expect(unreadEmailB).toBe(0); + }); }); describe('Load data thread from Email Table:', () => { diff --git a/email_mailbox/src/components/PanelWrapper.js b/email_mailbox/src/components/PanelWrapper.js index c43da8e34..4ec360692 100644 --- a/email_mailbox/src/components/PanelWrapper.js +++ b/email_mailbox/src/components/PanelWrapper.js @@ -149,7 +149,11 @@ class PanelWrapper extends Component { }); } if (isToMe) { - props.onUpdateUnreadEmailsBadge(); + props.onUpdateUnreadEmailsBadge({ + labelId: LabelType.inbox.id, + operation: 'add', + value: 1 + }); } }); @@ -166,8 +170,8 @@ class PanelWrapper extends Component { props.onLoadEmails(this.state.sectionSelected.params.threadIdSelected); } if (eventParams) { - const { operation, value } = eventParams; - props.onUpdateUnreadDraftBadge({ operation, value }); + const { labelId, operation, value } = eventParams; + props.onUpdateUnreadEmailsBadge({ labelId, operation, value }); } }); @@ -209,7 +213,11 @@ class PanelWrapper extends Component { emailIds: [oldEmailId] }); } else if (!newEmailId && !oldEmailId) { - props.onUpdateUnreadEmailsBadge(); + props.onUpdateUnreadEmailsBadge({ + labelId: LabelType.inbox.id, + operation: 'add', + value: 1 + }); } }); @@ -247,7 +255,6 @@ PanelWrapper.propTypes = { onUnsendEmail: PropTypes.func, onUpdateOpenedAccount: PropTypes.func, onUpdateTimestamp: PropTypes.func, - onUpdateUnreadDraftBadge: PropTypes.func, onUpdateUnreadEmailsBadge: PropTypes.func, onUpdateUnreadThreads: PropTypes.func, threadsCount: PropTypes.number diff --git a/email_mailbox/src/containers/Panel.js b/email_mailbox/src/containers/Panel.js index 546d6a5a6..95ed4c10e 100644 --- a/email_mailbox/src/containers/Panel.js +++ b/email_mailbox/src/containers/Panel.js @@ -73,17 +73,9 @@ const mapDispatchToProps = dispatch => { const recipientId = myAccount.recipientId; await updateAccount({ opened, recipientId }); }, - onUpdateUnreadEmailsBadge: () => { + onUpdateUnreadEmailsBadge: ({ labelId, operation, value }) => { const label = { - id: LabelType.inbox.id, - operation: 'add', - value: 1 - }; - dispatch(updateLabelSuccess(label)); - }, - onUpdateUnreadDraftBadge: ({ operation, value }) => { - const label = { - id: LabelType.draft.id, + id: labelId, operation, value }; diff --git a/email_mailbox/src/utils/electronEventInterface.js b/email_mailbox/src/utils/electronEventInterface.js index 71f86a525..0a2cf54e9 100644 --- a/email_mailbox/src/utils/electronEventInterface.js +++ b/email_mailbox/src/utils/electronEventInterface.js @@ -4,12 +4,14 @@ import { createEmail, createEmailLabel, getEmailByKey, + getEmailsByKeys, getEmailLabelsByEmailId, LabelType, getContactByEmails, createFeedItem, myAccount, updateEmail, + updateEmails, getLabelsByText, updateAccount, updateFilesByEmailId, @@ -267,15 +269,18 @@ const handlePeerEmailUnsend = async ({ rowid, params }) => { const handlePeerEmailRead = async ({ rowid, params }) => { const { metadataKeys, unread } = params; - for (const metadataKey of metadataKeys) { - const [email] = await getEmailByKey(metadataKey); - if (email) { - await updateEmail({ - key: metadataKey, - unread: unread - }); - } - } + const emails = await getEmailsByKeys(metadataKeys); + const emailKeys = emails.map(email => email.key); + await updateEmails({ + keys: emailKeys, + unread: !!unread + }); + const eventParams = { + labelId: LabelType.inbox.id, + operation: unread ? 'add' : 'less', + value: emailKeys.length + }; + emitter.emit(Event.REFRESH_THREADS, emailKeys.length ? eventParams : null); await setEventAsHandled(rowid); }; @@ -405,6 +410,10 @@ const setEventAsHandled = async eventId => { ----------------------------- */ ipcRenderer.on('update-drafts', (ev, data) => { + if (data) { + const labelId = LabelType.draft.id; + data = { ...data, labelId }; + } emitter.emit(Event.REFRESH_THREADS, data); }); diff --git a/email_mailbox/src/utils/electronInterface.js b/email_mailbox/src/utils/electronInterface.js index 43994783d..2e47caf94 100644 --- a/email_mailbox/src/utils/electronInterface.js +++ b/email_mailbox/src/utils/electronInterface.js @@ -210,6 +210,10 @@ export const getEmailByKey = emailKey => { return dbManager.getEmailByKey(emailKey); }; +export const getEmailsByKeys = emailKeys => { + return dbManager.getEmailsByKeys(emailKeys); +}; + export const getEmailsByLabelIds = labelIds => { return dbManager.getEmailsByLabelIds(labelIds); }; @@ -298,6 +302,10 @@ export const updateEmail = params => { return dbManager.updateEmail(params); }; +export const updateEmails = params => { + return dbManager.updateEmails(params); +}; + export const updateAccount = params => { return dbManager.updateAccount(params); };