Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/Envelope.vue1
-rw-r--r--src/components/MailboxThread.vue28
-rw-r--r--src/components/MenuEnvelope.vue1
-rw-r--r--src/components/Navigation.vue2
-rw-r--r--src/components/NewMessageModal.vue216
-rw-r--r--src/components/OutboxComposer.vue112
-rw-r--r--src/components/OutboxMessageListItem.vue21
-rw-r--r--src/store/actions.js36
-rw-r--r--src/store/getters.js5
-rw-r--r--src/store/mutations.js5
-rw-r--r--src/tests/setup.js1
11 files changed, 160 insertions, 268 deletions
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index 03fc6f545..95fdff205 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -397,6 +397,7 @@ export default {
async onOpenEditAsNew() {
await this.$store.dispatch('showMessageComposer', {
templateMessageId: this.data.databaseId,
+ data: this.data,
})
},
onOpenMoveModal() {
diff --git a/src/components/MailboxThread.vue b/src/components/MailboxThread.vue
index 07f513dc7..5ec230d49 100644
--- a/src/components/MailboxThread.vue
+++ b/src/components/MailboxThread.vue
@@ -85,6 +85,7 @@ import {
priorityOtherQuery,
priorityStarredQuery,
} from '../util/priorityInbox'
+import { detect, html } from '../util/text'
export default {
name: 'MailboxThread',
@@ -201,8 +202,33 @@ export default {
},
handleMailto() {
if (this.$route.name === 'message' && this.$route.params.threadId === 'mailto') {
- this.$store.dispatch('showMessageComposer')
+ let accountId
+ // Only preselect an account when we're not in a unified mailbox
+ if (this.$route.params.accountId !== 0 && this.$route.params.accountId !== '0') {
+ accountId = parseInt(this.$route.params.accountId, 10)
+ }
+ this.$store.dispatch('showMessageComposer', {
+ data: {
+ accountId,
+ to: this.stringToRecipients(this.$route.query.to),
+ cc: this.stringToRecipients(this.$route.query.cc),
+ subject: this.$route.query.subject || '',
+ body: this.$route.query.body ? detect(this.$route.query.body) : html(''),
+ },
+ })
+ }
+ },
+ stringToRecipients(str) {
+ if (str === undefined) {
+ return []
}
+
+ return [
+ {
+ label: str,
+ email: str,
+ },
+ ]
},
},
}
diff --git a/src/components/MenuEnvelope.vue b/src/components/MenuEnvelope.vue
index a3ccfed33..74a3cc7fc 100644
--- a/src/components/MenuEnvelope.vue
+++ b/src/components/MenuEnvelope.vue
@@ -386,6 +386,7 @@ export default {
async onOpenEditAsNew() {
await this.$store.dispatch('showMessageComposer', {
templateMessageId: this.envelope.databaseId,
+ data: this.envelope,
})
},
},
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index ba2e45d1b..fd821f0bd 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -117,7 +117,7 @@ export default {
},
data() {
return {
- refreshing: false
+ refreshing: false,
}
},
computed: {
diff --git a/src/components/NewMessageModal.vue b/src/components/NewMessageModal.vue
index 2dd6d390d..713ac867b 100644
--- a/src/components/NewMessageModal.vue
+++ b/src/components/NewMessageModal.vue
@@ -1,9 +1,9 @@
<template>
<Modal
size="normal"
- :title="t('mail', 'New message')"
+ :title="modalTitle"
@close="$emit('close')">
- <Composer v-if="!fetchingTemplateMessage"
+ <Composer
:from-account="composerData.accountId"
:to="composerData.to"
:cc="composerData.cc"
@@ -18,12 +18,9 @@
<script>
import Modal from '@nextcloud/vue/dist/Components/Modal'
import logger from '../logger'
-import { detect, html, plain, toPlain } from '../util/text'
+import { toPlain } from '../util/text'
import { saveDraft } from '../service/MessageService'
import Composer from './Composer'
-import { showWarning } from '@nextcloud/dialogs'
-import Axios from '@nextcloud/axios'
-import { generateUrl } from '@nextcloud/router'
import { translate as t } from '@nextcloud/l10n'
export default {
@@ -36,158 +33,101 @@ export default {
return {
original: undefined,
originalBody: undefined,
- fetchingTemplateMessage: true,
}
},
computed: {
- forwardedMessages() {
- return this.$store.getters.messageComposerOptions?.forwardedMessages ?? []
+ modalTitle() {
+ if (this.composerMessage.type === 'outbox') {
+ return t('mail', 'Outbox draft')
+ }
+ return t('mail', 'New message')
},
- templateMessageId() {
- return this.$store.getters.messageComposerOptions?.templateMessageId
+ composerMessage() {
+ return this.$store.getters.composerMessage
},
composerData() {
- logger.debug('composing a new message or handling a mailto link', {
- threadId: this.$route.params.threadId,
- })
-
- let accountId
- // Only preselect an account when we're not in a unified mailbox
- if (this.$route.params.accountId !== 0 && this.$route.params.accountId !== '0') {
- accountId = parseInt(this.$route.params.accountId, 10)
- }
- if (this.templateMessageId !== undefined) {
- if (this.original.attachments.length) {
- showWarning(t('mail', 'Attachments were not copied. Please add them manually.'))
- }
-
- return {
- accountId: this.original.accountId,
- to: this.original.to,
- cc: this.original.cc,
- subject: this.original.subject,
- body: this.originalBody,
- originalBody: this.originalBody,
- }
- }
-
- return {
- accountId,
- to: this.stringToRecipients(this.$route.query.to),
- cc: this.stringToRecipients(this.$route.query.cc),
- subject: this.$route.query.subject || '',
- body: this.$route.query.body ? detect(this.$route.query.body) : html(''),
- }
+ return this.$store.getters.composerMessage?.data
+ },
+ forwardedMessages() {
+ return this.composerMessage?.options?.forwardedMessages ?? []
},
- },
- created() {
- this.fetchOriginalMessage()
},
methods: {
- stringToRecipients(str) {
- if (str === undefined) {
- return []
- }
-
- return [
- {
- label: str,
- email: str,
- },
- ]
- },
async saveDraft(data) {
- if (data.draftId === undefined && this.draft) {
- logger.debug('draft data does not have a draftId, adding one', {
- draft: this.draft,
- data,
- id: this.draft.databaseId,
- })
- data.draftId = this.draft.databaseId
- }
- const dataForServer = {
- ...data,
- to: data.to.map(this.recipientToRfc822).join(', '),
- cc: data.cc.map(this.recipientToRfc822).join(', '),
- bcc: data.bcc.map(this.recipientToRfc822).join(', '),
- body: data.isHtml ? data.body.value : toPlain(data.body).value,
- }
- const { id } = await saveDraft(data.account, dataForServer)
+ if (this.composerMessage.type === 'outbox') {
+ const dataForServer = {
+ ...data,
+ body: data.isHtml ? data.body.value : toPlain(data.body).value,
+ }
+ await this.$store.dispatch('outbox/updateMessage', { message: dataForServer, id: this.composerData.id })
+ } else {
+ const dataForServer = {
+ ...data,
+ to: data.to.map(this.recipientToRfc822).join(', '),
+ cc: data.cc.map(this.recipientToRfc822).join(', '),
+ bcc: data.bcc.map(this.recipientToRfc822).join(', '),
+ body: data.isHtml ? data.body.value : toPlain(data.body).value,
+ }
+ const { id } = await saveDraft(data.account, dataForServer)
- // Remove old draft envelope
- this.$store.commit('removeEnvelope', { id: data.draftId })
- this.$store.commit('removeMessage', { id: data.draftId })
+ // Remove old draft envelope
+ this.$store.commit('removeEnvelope', { id: data.draftId })
+ this.$store.commit('removeMessage', { id: data.draftId })
- // Fetch new draft envelope
- await this.$store.dispatch('fetchEnvelope', id)
+ // Fetch new draft envelope
+ await this.$store.dispatch('fetchEnvelope', id)
- return id
+ return id
+ }
},
async sendMessage(data) {
logger.debug('sending message', { data })
- const now = new Date().getTime()
- const dataForServer = {
- accountId: data.account,
- sendAt: Math.floor(now / 1000), // JS timestamp is in milliseconds
- subject: data.subject,
- body: data.isHtml ? data.body.value : toPlain(data.body).value,
- isHtml: data.isHtml,
- isMdn: false,
- inReplyToMessageId: '',
- to: data.to,
- cc: data.cc,
- bcc: data.bcc,
- attachmentIds: [],
- }
- const message = await this.$store.dispatch('outbox/enqueueMessage', {
- message: dataForServer,
- })
-
- await this.$store.dispatch('outbox/sendMessage', { id: message.id })
-
- // Remove old draft envelope
- this.$store.commit('removeEnvelope', { id: data.draftId })
- this.$store.commit('removeMessage', { id: data.draftId })
- },
- async fetchOriginalMessage() {
- if (this.templateMessageId === undefined) {
- this.fetchingTemplateMessage = false
- return
- }
- this.loading = true
- this.error = undefined
- this.errorMessage = ''
-
- logger.debug(`fetching original message ${this.templateMessageId}`)
+ if (this.composerMessage.type === 'outbox') {
+ const now = new Date().getTime()
+ const dataForServer = {
+ accountId: data.account,
+ sendAt: Math.floor(now / 1000), // JS timestamp is in milliseconds
+ subject: data.subject,
+ body: data.isHtml ? data.body.value : toPlain(data.body).value,
+ isHtml: data.isHtml,
+ isMdn: false,
+ inReplyToMessageId: '',
+ to: data.to,
+ cc: data.cc,
+ bcc: data.bcc,
+ attachmentIds: [],
+ }
+ // TODO: update the message instead of enqueing another time
+ const message = await this.$store.dispatch('outbox/enqueueMessage', {
+ message: dataForServer,
+ })
- try {
- const message = await this.$store.dispatch('fetchMessage', this.templateMessageId)
- logger.debug('original message fetched', { message })
- this.original = message
+ await this.$store.dispatch('outbox/sendMessage', { id: message.id })
+ } else {
+ const now = new Date().getTime()
+ const dataForServer = {
+ accountId: data.account,
+ sendAt: Math.floor(now / 1000), // JS timestamp is in milliseconds
+ subject: data.subject,
+ body: data.isHtml ? data.body.value : toPlain(data.body).value,
+ isHtml: data.isHtml,
+ isMdn: false,
+ inReplyToMessageId: '',
+ to: data.to,
+ cc: data.cc,
+ bcc: data.bcc,
+ attachmentIds: [],
+ }
+ const message = await this.$store.dispatch('outbox/enqueueMessage', {
+ message: dataForServer,
+ })
- let body = plain(message.body || '')
- if (message.hasHtmlBody) {
- logger.debug('original message has HTML body')
- const resp = await Axios.get(
- generateUrl('/apps/mail/api/messages/{id}/html?plain=true', {
- Id: this.templateMessageId,
- })
- )
+ await this.$store.dispatch('outbox/sendMessage', { id: message.id })
- body = html(resp.data)
- }
- this.originalBody = body
- } catch (error) {
- logger.error('could not load original message ' + this.templateMessageId, { error })
- if (error.isError) {
- this.errorMessage = t('mail', 'Could not load original message')
- this.error = error
- this.loading = false
- }
- } finally {
- this.loading = false
+ // Remove old draft envelope
+ this.$store.commit('removeEnvelope', { id: data.draftId })
+ this.$store.commit('removeMessage', { id: data.draftId })
}
- this.fetchingTemplateMessage = false
},
recipientToRfc822(recipient) {
if (recipient.email === recipient.label) {
diff --git a/src/components/OutboxComposer.vue b/src/components/OutboxComposer.vue
deleted file mode 100644
index 0a90a8f53..000000000
--- a/src/components/OutboxComposer.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-<template>
- <Modal
- size="normal"
- :title="t('mail', 'Outbox draft')"
- @close="$emit('close')">
- <Composer
- :from-account="message.accountId"
- :to="message.to"
- :cc="message.cc"
- :bcc="message.bcc"
- :subject="message.subject"
- :body="outboxBody"
- :draft="saveDraft"
- :send="sendMessage" />
- </Modal>
-</template>
-<script>
-import Modal from '@nextcloud/vue/dist/Components/Modal'
-import logger from '../logger'
-import { html, plain, toPlain } from '../util/text'
-import Composer from './Composer'
-
-export default {
- name: 'OutboxComposer',
- components: {
- Modal,
- Composer,
- },
- props: {
- message: {
- type: Object,
- required: true,
- },
- },
- computed: {
- outboxBody() {
- if (this.message.html) {
- return html(this.message.text)
- }
- return plain(this.message.text)
- },
- },
- methods: {
- stringToRecipients(str) {
- if (str === undefined) {
- return []
- }
-
- return [
- {
- label: str,
- email: str,
- },
- ]
- },
- async saveDraft(data) {
- if (data.draftId === undefined && this.draft) {
- logger.debug('draft data does not have a draftId, adding one', {
- draft: this.draft,
- data,
- id: this.draft.databaseId,
- })
- data.draftId = this.draft.databaseId
- }
- const dataForServer = {
- ...data,
- body: data.isHtml ? data.body.value : toPlain(data.body).value,
- }
- await this.$store.dispatch('outbox/updateMessage', { message: dataForServer, id: this.message.id })
- },
- async sendMessage(data) {
- logger.debug('sending message', { data })
- const now = new Date().getTime()
- const dataForServer = {
- accountId: data.account,
- sendAt: Math.floor(now / 1000), // JS timestamp is in milliseconds
- subject: data.subject,
- body: data.isHtml ? data.body.value : toPlain(data.body).value,
- isHtml: data.isHtml,
- isMdn: false,
- inReplyToMessageId: '',
- to: data.to,
- cc: data.cc,
- bcc: data.bcc,
- attachmentIds: [],
- }
- const message = await this.$store.dispatch('outbox/enqueueMessage', {
- message: dataForServer,
- })
-
- await this.$store.dispatch('outbox/sendMessage', { id: message.id })
- },
- },
-}
-
-</script>
-
-<style lang="scss" scoped>
-@media only screen and (max-width: 600px) {
- ::v-deep .modal-container {
- max-width: 80%;
- }
-}
-::v-deep .modal-container {
- width: 80%;
- min-height: 60%;
-}
-::v-deep .modal-wrapper .modal-container {
- overflow-y: auto !important;
- overflow-x: auto !important;
-}
-</style>
diff --git a/src/components/OutboxMessageListItem.vue b/src/components/OutboxMessageListItem.vue
index b3fb86edd..74cb65e37 100644
--- a/src/components/OutboxMessageListItem.vue
+++ b/src/components/OutboxMessageListItem.vue
@@ -49,9 +49,6 @@
{{ t('mail', 'Delete message') }}
</ActionButton>
</template>
- <template #extra>
- <OutboxComposer v-if="showOutboxComposer" :message="message" @close="showOutboxComposer = false;" />
- </template>
</ListItem>
</template>
@@ -65,7 +62,7 @@ import logger from '../logger'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { matchError } from '../errors/match'
import { translate as t } from '@nextcloud/l10n'
-import OutboxComposer from './OutboxComposer'
+import { html, plain } from '../util/text'
export default {
name: 'OutboxMessageListItem',
@@ -73,7 +70,6 @@ export default {
ListItem,
Avatar,
ActionButton,
- OutboxComposer,
},
mixins: [
OutboxAvatarMixin,
@@ -84,11 +80,6 @@ export default {
required: true,
},
},
- data() {
- return {
- showOutboxComposer: false,
- }
- },
computed: {
selected() {
return this.$route.params.messageId === this.message.id
@@ -121,8 +112,14 @@ export default {
await this.$store.dispatch('outbox/sendMessage', { id: this.message.id })
showSuccess(t('mail', 'Message sent'))
},
- openModal() {
- this.showOutboxComposer = true
+ async openModal() {
+ await this.$store.dispatch('showMessageComposer', {
+ type: 'outbox',
+ data: {
+ ...this.message,
+ body: this.message.html ? html(this.message.text) : plain(this.message.text),
+ },
+ })
},
},
}
diff --git a/src/store/actions.js b/src/store/actions.js
index e18243545..8c5180d1f 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -82,6 +82,11 @@ import { updateAccount as updateSieveAccount } from '../service/SieveService'
import { PAGE_SIZE, UNIFIED_INBOX_ID } from './constants'
import * as ThreadService from '../service/ThreadService'
import { getPrioritySearchQueries } from '../util/priorityInbox'
+import { html, plain } from '../util/text'
+import Axios from '@nextcloud/axios'
+import { generateUrl } from '@nextcloud/router'
+import { showWarning } from '@nextcloud/dialogs'
+import { translate as t } from '@nextcloud/l10n'
const sliceToPage = slice(0, PAGE_SIZE)
@@ -253,8 +258,37 @@ export default {
updated,
})
},
- async showMessageComposer({ commit }, { forwardedMessages = [], templateMessageId = undefined }) {
+ async showMessageComposer({ commit, dispatch }, { type = 'imap', data = {}, forwardedMessages = [], templateMessageId }) {
+ if (templateMessageId) {
+ const message = await dispatch('fetchMessage', templateMessageId)
+ // Merge the original into any existing data
+ data = {
+ ...data,
+ message,
+ }
+
+ // Fetch and transform the body into a rich text object
+ if (message.hasHtmlBody) {
+ const resp = await Axios.get(
+ generateUrl('/apps/mail/api/messages/{id}/html?plain=true', {
+ id: templateMessageId,
+ })
+ )
+
+ data.body = html(resp.data)
+ } else {
+ data.body = plain(message.body)
+ }
+
+ // TODO: implement attachments
+ if (message.attachments.length) {
+ showWarning(t('mail', 'Attachments were not copied. Please add them manually.'))
+ }
+ }
+
commit('showMessageComposer', {
+ type,
+ data,
forwardedMessages,
templateMessageId,
})
diff --git a/src/store/getters.js b/src/store/getters.js
index 5c87d45c7..255c65fa1 100644
--- a/src/store/getters.js
+++ b/src/store/getters.js
@@ -57,7 +57,10 @@ export const getters = {
showMessageComposer: (state) => {
return state.newMessage !== undefined
},
- messageComposerOptions: (state) => {
+ composerMessage: (state) => {
+ return state.newMessage
+ },
+ composerMessageOptions: (state) => {
return state.newMessage?.options
},
getEnvelope: (state) => (id) => {
diff --git a/src/store/mutations.js b/src/store/mutations.js
index ff9c8efc0..9bb71337e 100644
--- a/src/store/mutations.js
+++ b/src/store/mutations.js
@@ -174,11 +174,12 @@ export default {
}
removeRec(account)
},
- showMessageComposer(state, { forwardedMessages, templateMessageId }) {
+ showMessageComposer(state, { type, data, forwardedMessages }) {
Vue.set(state, 'newMessage', {
+ type,
+ data,
options: {
forwardedMessages,
- templateMessageId,
},
})
},
diff --git a/src/tests/setup.js b/src/tests/setup.js
index 1862490f1..2972909ab 100644
--- a/src/tests/setup.js
+++ b/src/tests/setup.js
@@ -37,6 +37,7 @@ global.SVGElement = global.Element
global.OC = {
getLocale: () => 'en',
+ getLanguage: () => 'en_US',
L10N: {
translate: (app, string) => {
if (app !== 'mail') {