diff --git a/program/actions/mail/compose.php b/program/actions/mail/compose.php index 772089437e..93843dcee6 100644 --- a/program/actions/mail/compose.php +++ b/program/actions/mail/compose.php @@ -106,7 +106,8 @@ public function run($args = []) 'selectimportfile', 'messageissent', 'loadingdata', 'nopubkeyfor', 'nopubkeyforsender', 'encryptnoattachments', 'encryptedsendialog', 'searchpubkeyservers', 'importpubkeys', 'encryptpubkeysfound', 'search', 'close', 'import', 'keyid', 'keylength', 'keyexpired', - 'keyrevoked', 'keyimportsuccess', 'keyservererror', 'attaching', 'namex', 'attachmentrename' + 'keyrevoked', 'keyimportsuccess', 'keyservererror', 'attaching', 'namex', 'attachmentrename', + 'deletingmessage', 'discardmessage', 'draftdiscarded', 'discarddraftwarning' ); $rcmail->output->set_pagetitle($rcmail->gettext('compose')); diff --git a/program/actions/mail/delete.php b/program/actions/mail/delete.php index 49d4721b13..a89abce8b9 100644 --- a/program/actions/mail/delete.php +++ b/program/actions/mail/delete.php @@ -56,12 +56,24 @@ public function run($args = []) if (empty($deleted)) { // send error message - if ($_POST['_from'] != 'show') { + if ($_POST['_from'] != 'show' && $_POST['_from'] != 'compose') { $rcmail->output->command('list_mailbox'); } self::display_server_error('errordeleting'); $rcmail->output->send(); + } elseif (!empty($_POST['_from']) && $_POST['_from'] == 'compose') { + $COMPOSE_ID = rcube_utils::get_input_string('_compose_id', rcube_utils::INPUT_POST); + $COMPOSE = &$_SESSION['compose_data_' . $COMPOSE_ID]; + + // Sanity checks + if (isset($COMPOSE['id'])) { + self::delete_compose_data($COMPOSE_ID); + } + + $drafts_mbox = $rcmail->config->get('drafts_mbox'); + $rcmail->output->command('sent_successfully', 'confirmation', $rcmail->gettext('draftdiscarded'), [$drafts_mbox]); + $rcmail->output->send(); } else { $rcmail->output->show_message('messagedeleted', 'confirmation'); } @@ -136,4 +148,14 @@ public function run($args = []) // send response $rcmail->output->send(); } + + public static function delete_compose_data($COMPOSE_ID) + { + $rcmail = rcmail::get_instance(); + $rcmail->delete_uploaded_files($COMPOSE_ID); + $rcmail->session->remove('compose_data_' . $COMPOSE_ID); + $_SESSION['last_compose_session'] = $COMPOSE_ID; + + $rcmail->output->command('remove_compose_data', $COMPOSE_ID); + } } diff --git a/program/actions/mail/send.php b/program/actions/mail/send.php index a47613247f..cf46993188 100644 --- a/program/actions/mail/send.php +++ b/program/actions/mail/send.php @@ -298,11 +298,7 @@ public function run($args = []) $save_error = true; } else { - $rcmail->delete_uploaded_files($COMPOSE_ID); - $rcmail->session->remove('compose_data_' . $COMPOSE_ID); - $_SESSION['last_compose_session'] = $COMPOSE_ID; - - $rcmail->output->command('remove_compose_data', $COMPOSE_ID); + rcmail_action_mail_delete::delete_compose_data($COMPOSE_ID); if ($store_folder) { $folders[] = $store_target; diff --git a/program/js/app.js b/program/js/app.js index d80a2f7d22..7bddf771e1 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -407,7 +407,7 @@ function rcube_webmail() { 'download-attachment', 'open-attachment', 'rename-attachment']; if (this.env.drafts_mailbox) { - this.env.compose_commands.push('savedraft'); + this.env.compose_commands.push('savedraft', 'delete'); } this.enable_command(this.env.compose_commands, true); @@ -840,13 +840,7 @@ function rcube_webmail() { && !this.compose_skip_unsavedcheck ) { if (!this.env.is_sent && this.cmp_hash != this.compose_field_hash()) { - this.confirm_dialog(this.get_label('notsentwarning'), 'discard', function () { - // remove copy from local storage if compose screen is left intentionally - ref.remove_compose_data(ref.env.compose_id); - ref.compose_skip_unsavedcheck = true; - ref.command(command, props, obj, event); - }); - + this.discard_draft(null, command, props, obj, event); return false; } } @@ -1130,8 +1124,12 @@ function rcube_webmail() { break; case 'delete': + // mail: discard draft + if (this.task == 'mail' && this.env.action == 'compose') { + this.discard_draft(this.env.draft_id); + } // mail task - if (this.task == 'mail') { + else if (this.task == 'mail') { this.delete_messages(event); } // addressbook task @@ -3565,6 +3563,30 @@ function rcube_webmail() { this.show_contentframe(false); }; + this.discard_draft = function (uid, command, props, obj, event) { + var msg = uid ? this.get_label('discarddraftwarning') : this.get_label('notsentwarning'); + this.confirm_dialog(msg, 'discard', function () { + if (uid) { + // if a draft has been saved then delete it + var post_data = ref.selection_post_data({ _uid: uid, _compose_id: ref.env.compose_id }); + post_data._mbox = ref.env.drafts_mailbox; + ref.with_selected_messages('delete', post_data); + } + else { + // remove copy from local storage if compose screen is left intentionally + ref.remove_compose_data(ref.env.compose_id); + + if (command) { + ref.compose_skip_unsavedcheck = true; + ref.command(command, props, obj, event); + } + else { + ref.sent_successfully('confirmation', 'draftdiscarded'); + } + } + }); + }; + // Send a specific move/delete request with UIDs of all selected messages this.with_selected_messages = function (action, post_data, lock, http_action) { var msg, count = 0, @@ -3878,7 +3900,9 @@ function rcube_webmail() { this.set_button_titles = function () { var label = 'deletemessage'; - if (!this.env.flag_for_deletion + if (this.env.action == 'compose') { + label = 'discardmessage'; + } else if (!this.env.flag_for_deletion && this.env.trash_mailbox && this.env.mailbox != this.env.trash_mailbox && (!this.env.delete_junk || !this.env.junk_mailbox || this.env.mailbox != this.env.junk_mailbox) ) { diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc index bab851966e..a410eca1ef 100644 --- a/program/localization/en_US/labels.inc +++ b/program/localization/en_US/labels.inc @@ -277,6 +277,7 @@ $labels['editasnew'] = 'Edit as new'; $labels['send'] = 'Send'; $labels['sendmessage'] = 'Send message'; $labels['savemessage'] = 'Save as draft'; +$labels['discardmessage'] = 'Discard draft'; $labels['addattachment'] = 'Attach a file'; $labels['charset'] = 'Charset'; $labels['editortype'] = 'Editor type'; diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index 01ed1fe536..62c9c8fd3c 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -48,6 +48,7 @@ $messages['sendingmessage'] = 'Sending message...'; $messages['messagesent'] = 'Message sent successfully.'; $messages['savingmessage'] = 'Saving message...'; $messages['messagesaved'] = 'Message saved to Drafts.'; +$messages['draftdiscarded'] = 'Draft discarded.'; $messages['successfullysaved'] = 'Successfully saved.'; $messages['savingresponse'] = 'Saving response text...'; $messages['deleteresponseconfirm'] = 'Do you really want to delete this response text?'; @@ -107,6 +108,7 @@ $messages['nosubjectwarning'] = 'The "Subject" field is empty. Would you like t $messages['nosubjecttitle'] = 'No subject'; $messages['nobodywarning'] = 'Send this message without text?'; $messages['notsentwarning'] = 'The message has not been sent and has unsaved changes. Do you want to discard your changes?'; +$messages['discarddraftwarning'] = 'Do you want to discard your saved draft and any unsaved changes of this message?'; $messages['restoresavedcomposedata'] = 'A previously composed but unsent message was found.\n\nSubject: $subject\nSaved: $date\n\nDo you want to restore this message?'; $messages['nosearchname'] = 'Please enter a contact name or email address.'; $messages['notuploadedwarning'] = 'Not all attachments have been uploaded yet. Please wait or cancel the upload.'; diff --git a/skins/elastic/styles/widgets/menu.less b/skins/elastic/styles/widgets/menu.less index d15ccffdce..aa77e56239 100644 --- a/skins/elastic/styles/widgets/menu.less +++ b/skins/elastic/styles/widgets/menu.less @@ -499,7 +499,8 @@ a.toolbar-button { &.create:before { content: @fa-var-plus-square; } - &.delete:before { + &.delete:before, + &.discard:before { content: @fa-var-trash-alt; } &.download:before, diff --git a/skins/elastic/templates/compose.html b/skins/elastic/templates/compose.html index 3a819daef7..d11b362943 100644 --- a/skins/elastic/templates/compose.html +++ b/skins/elastic/templates/compose.html @@ -114,6 +114,9 @@

+ +