diff options
author | Richard Steinmetz <richard@steinmetz.cloud> | 2022-04-29 16:19:32 +0300 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2022-05-02 17:55:17 +0300 |
commit | d7787919198fafc0971f0e3fb4a157436f8ea691 (patch) | |
tree | e93205697961db78379d6052ad05b9cea8a2adf8 /src | |
parent | 8e75eb56aa44ab681acf66f15cc757ee617552b3 (diff) |
Implement undo for send now action in outbox message list
Signed-off-by: Richard Steinmetz <richard@steinmetz.cloud>
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'src')
-rw-r--r-- | src/components/NewMessageModal.vue | 36 | ||||
-rw-r--r-- | src/components/OutboxMessageListItem.vue | 16 | ||||
-rw-r--r-- | src/store/outbox/actions.js | 66 |
3 files changed, 77 insertions, 41 deletions
diff --git a/src/components/NewMessageModal.vue b/src/components/NewMessageModal.vue index 41f7d30da..faa1d3362 100644 --- a/src/components/NewMessageModal.vue +++ b/src/components/NewMessageModal.vue @@ -27,7 +27,7 @@ import logger from '../logger' import { toPlain } from '../util/text' import { saveDraft } from '../service/MessageService' import Composer from './Composer' -import { showError, showSuccess, showUndo } from '@nextcloud/dialogs' +import { showError, showSuccess } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' import { UNDO_DELAY } from '../store/constants' @@ -127,46 +127,20 @@ export default { dataForServer.sendAt = Math.floor((now + UNDO_DELAY) / 1000) } - let message if (!this.composerData.id) { - message = await this.$store.dispatch('outbox/enqueueMessage', { + await this.$store.dispatch('outbox/enqueueMessage', { message: dataForServer, }) } else { - message = await this.$store.dispatch('outbox/updateMessage', { + await this.$store.dispatch('outbox/updateMessage', { message: dataForServer, id: this.composerData.id, }) } if (!data.sendAt || data.sendAt < Math.floor((now + UNDO_DELAY) / 1000)) { - showUndo( - t('mail', 'Message sent'), - async() => { - logger.info('Attempting to stop sending message ' + message.id) - const stopped = await this.$store.dispatch('outbox/stopMessage', { message }) - logger.info('Message ' + message.id + ' stopped', { message: stopped }) - await this.$store.dispatch('showMessageComposer', { - type: 'outbox', - data: { - ...message, // For id and other properties - ...data, // For the correct body values - }, - }) - }, { - timeout: UNDO_DELAY, - close: true, - } - ) - - setTimeout(() => { - try { - this.$store.dispatch('outbox/sendMessage', { id: message.id }) - } catch (error) { - showError(t('mail', 'Could not send message')) - logger.error('Could not delay-send message ' + message.id, { message }) - } - }, UNDO_DELAY) + // Awaiting here would keep the modal open for a long time and thus block the user + this.$store.dispatch('outbox/sendMessageWithUndo', { id: this.composerData.id }) } if (data.draftId) { // Remove old draft envelope diff --git a/src/components/OutboxMessageListItem.vue b/src/components/OutboxMessageListItem.vue index 35793bcb0..69520eb7d 100644 --- a/src/components/OutboxMessageListItem.vue +++ b/src/components/OutboxMessageListItem.vue @@ -40,7 +40,7 @@ <ActionButton icon="icon-checkmark" :close-after-click="true" - @click="sendMessage"> + @click="sendMessageNow"> {{ t('mail', 'Send now') }} <template #icon> <Send @@ -71,6 +71,7 @@ import { showError, showSuccess } from '@nextcloud/dialogs' import { matchError } from '../errors/match' import { html, plain } from '../util/text' import Send from 'vue-material-design-icons/Send' +import { UNDO_DELAY } from '../store/constants' export default { name: 'OutboxMessageListItem', @@ -128,14 +129,13 @@ export default { })) } }, - async sendMessage(data) { - logger.debug('sending message', { data }) - try { - await this.$store.dispatch('outbox/sendMessage', { id: this.message.id, force: true }) - showSuccess(t('mail', 'Message sent')) - } catch (error) { - showError(t('mail', 'Could not send message')) + async sendMessageNow() { + const message = { + ...this.message, + sendAt: (new Date().getTime() + UNDO_DELAY) / 1000, } + await this.$store.dispatch('outbox/updateMessage', { message, id: message.id }) + await this.$store.dispatch('outbox/sendMessageWithUndo', { id: message.id }) }, async openModal() { await this.$store.dispatch('showMessageComposer', { diff --git a/src/store/outbox/actions.js b/src/store/outbox/actions.js index 397de6d0b..ccfd58604 100644 --- a/src/store/outbox/actions.js +++ b/src/store/outbox/actions.js @@ -22,7 +22,10 @@ import * as OutboxService from '../../service/OutboxService' import logger from '../../logger' +import { showError, showUndo } from '@nextcloud/dialogs' +import { translate as t } from '@nextcloud/l10n' import { UNDO_DELAY } from '../constants' +import { html, plain } from '../../util/text' export default { async fetchMessages({ getters, commit }) { @@ -87,18 +90,29 @@ export default { return updatedMessage }, + /** + * Send an outbox message right now. + * + * @param {object} store Vuex destructuring object + * @param {function} store.commit Vuex commit object + * @param {object} store.getters Vuex getters object + * @param {object} data Action data + * @param {number} data.id Id of outbox message to send + * @param {boolean} data.force Force sending a message even if it has no sendAt timestamp + * @returns {Promise<boolean>} Resolves to false if sending was skipped + */ async sendMessage({ commit, getters }, { id, force = false }) { // Skip if the message has been deleted/undone in the meantime const message = getters.getMessage(id) logger.debug('Sending message ' + id, { message, force }) if (!force && (!message || !message.sendAt)) { logger.debug('Skipped sending message that was undone') - return + return false } if (message.sendAt * 1000 > new Date().getTime() + UNDO_DELAY) { logger.debug('Skipped sending message that is scheduled for the future') - return + return false } try { @@ -110,5 +124,53 @@ export default { } commit('deleteMessage', { id }) + return true + }, + + /** + * Wait for UNDO_DELAY before sending the message and show a toast with an undo action. + * + * @param {object} store Vuex destructuring object + * @param {function} store.dispatch Vuex dispatch object + * @param {object} store.getters Vuex getters object + * @param {object} data Action data + * @param {number} data.id Id of outbox message to send + * @returns {Promise<boolean>} Resolves to false if sending was skipped. Resolves after UNDO_DELAY has elapsed and the message dispatch was triggered. Warning: This might take a long time, depending on UNDO_DELAY. + */ + async sendMessageWithUndo({ getters, dispatch }, { id }) { + return new Promise((resolve, reject) => { + const message = getters.getMessage(id) + + showUndo( + t('mail', 'Message sent'), + async() => { + logger.info('Attempting to stop sending message ' + message.id) + const stopped = await dispatch('stopMessage', { message }) + logger.info('Message ' + message.id + ' stopped', { message: stopped }) + await dispatch('showMessageComposer', { + type: 'outbox', + data: { + ...message, + // The composer expects rich body data and not just a string + body: message.isHtml ? html(message.body) : plain(message.body), + }, + }, { root: true }) + }, { + timeout: UNDO_DELAY, + close: true, + } + ) + + setTimeout(async() => { + try { + const wasSent = await dispatch('sendMessage', { id: message.id }) + resolve(wasSent) + } catch (error) { + showError(t('mail', 'Could not send message')) + logger.error('Could not delay-send message ' + message.id, { message }) + reject(error) + } + }, UNDO_DELAY) + }) }, } |