diff --git a/images/drawable-src/btn_edit.png b/images/drawable-src/btn_edit.png new file mode 100644 index 000000000..666ffe8a4 Binary files /dev/null and b/images/drawable-src/btn_edit.png differ diff --git a/images/drawable-src/btn_empty_disable.png b/images/drawable-src/btn_empty_disable.png new file mode 100644 index 000000000..486fc0694 Binary files /dev/null and b/images/drawable-src/btn_empty_disable.png differ diff --git a/images/drawable-src/btn_empty_normal.png b/images/drawable-src/btn_empty_normal.png new file mode 100644 index 000000000..efa36e8b8 Binary files /dev/null and b/images/drawable-src/btn_empty_normal.png differ diff --git a/images/drawable-src/btn_empty_pressed.png b/images/drawable-src/btn_empty_pressed.png new file mode 100644 index 000000000..5293a86ba Binary files /dev/null and b/images/drawable-src/btn_empty_pressed.png differ diff --git a/images/drawable-src/btn_empty_selected.png b/images/drawable-src/btn_empty_selected.png new file mode 100644 index 000000000..e9ee03677 Binary files /dev/null and b/images/drawable-src/btn_empty_selected.png differ diff --git a/res/drawable-hdpi/btn_edit_disable.png b/res/drawable-hdpi/btn_edit_disable.png new file mode 100644 index 000000000..e21d11018 Binary files /dev/null and b/res/drawable-hdpi/btn_edit_disable.png differ diff --git a/res/drawable-hdpi/btn_edit_normal.png b/res/drawable-hdpi/btn_edit_normal.png new file mode 100644 index 000000000..edc2f7a15 Binary files /dev/null and b/res/drawable-hdpi/btn_edit_normal.png differ diff --git a/res/drawable-hdpi/btn_edit_pressed.png b/res/drawable-hdpi/btn_edit_pressed.png new file mode 100644 index 000000000..66d07eaf5 Binary files /dev/null and b/res/drawable-hdpi/btn_edit_pressed.png differ diff --git a/res/drawable-hdpi/btn_edit_selected.png b/res/drawable-hdpi/btn_edit_selected.png new file mode 100644 index 000000000..8e2b366d2 Binary files /dev/null and b/res/drawable-hdpi/btn_edit_selected.png differ diff --git a/res/drawable/btn_edit.xml b/res/drawable/btn_edit.xml new file mode 100644 index 000000000..1002498c6 --- /dev/null +++ b/res/drawable/btn_edit.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/res/layout/message_compose.xml b/res/layout/message_compose.xml index a2517341d..6139c4809 100644 --- a/res/layout/message_compose.xml +++ b/res/layout/message_compose.xml @@ -213,13 +213,31 @@ android:layout_height="wrap_content" android:layout_width="fill_parent" /> - + android:layout_alignParentRight="true"> + + + + + + diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java index 819517af9..74ebdf4d9 100644 --- a/src/com/fsck/k9/activity/MessageCompose.java +++ b/src/com/fsck/k9/activity/MessageCompose.java @@ -104,6 +104,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private static final String STATE_PGP_DATA = "pgpData"; private static final String STATE_IN_REPLY_TO = "com.fsck.k9.activity.MessageCompose.inReplyTo"; private static final String STATE_REFERENCES = "com.fsck.k9.activity.MessageCompose.references"; + private static final String STATE_KEY_MESSAGE_FORMAT = "com.fsck.k9.activity.MessageCompose.messageFormat"; private static final int MSG_PROGRESS_ON = 1; private static final int MSG_PROGRESS_OFF = 2; @@ -164,6 +165,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private EditText mMessageContentView; private LinearLayout mAttachments; private View mQuotedTextBar; + private ImageButton mQuotedTextEdit; private ImageButton mQuotedTextDelete; private EditText mQuotedText; private MessageWebView mQuotedHTML; @@ -179,6 +181,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private String mReferences; private String mInReplyTo; + private boolean mSourceProcessed = false; + private MessageFormat mMessageFormat; + private boolean mDraftNeedsSaving = false; private boolean mPreventDraftSaving = false; @@ -381,6 +386,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mMessageContentView.getInputExtras(true).putBoolean("allowEmoji", true); mAttachments = (LinearLayout)findViewById(R.id.attachments); mQuotedTextBar = findViewById(R.id.quoted_text_bar); + mQuotedTextEdit = (ImageButton)findViewById(R.id.quoted_text_edit); mQuotedTextDelete = (ImageButton)findViewById(R.id.quoted_text_delete); mQuotedText = (EditText)findViewById(R.id.quoted_text); mQuotedText.getInputExtras(true).putBoolean("allowEmoji", true); @@ -442,7 +448,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mQuotedTextBar.setVisibility(View.GONE); mQuotedText.setVisibility(View.GONE); mQuotedHTML.setVisibility(View.GONE); + mQuotedTextEdit.setVisibility(View.GONE); + mQuotedTextEdit.setOnClickListener(this); mQuotedTextDelete.setOnClickListener(this); mFromView.setVisibility(View.GONE); @@ -496,6 +504,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mSignatureView.setVisibility(View.GONE); } + mMessageFormat = mAccount.getMessageFormat(); + if (!mSourceMessageProcessed) { updateFrom(); @@ -830,6 +840,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc outState.putString(STATE_IN_REPLY_TO, mInReplyTo); outState.putString(STATE_REFERENCES, mReferences); outState.putSerializable(STATE_KEY_HTML_QUOTE, mQuotedHtmlContent); + outState.putSerializable(STATE_KEY_MESSAGE_FORMAT, mMessageFormat); } @Override @@ -844,9 +855,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc addAttachment(uri); } + mMessageFormat = (MessageFormat)savedInstanceState.getSerializable(STATE_KEY_MESSAGE_FORMAT); mCcView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_CC_SHOWN) ? View.VISIBLE : View.GONE); mBccView.setVisibility(savedInstanceState.getBoolean(STATE_KEY_BCC_SHOWN) ? View.VISIBLE : View.GONE); - if (mAccount.getMessageFormat() == MessageFormat.HTML) + if (mMessageFormat == MessageFormat.HTML) { mQuotedHtmlContent = (InsertableHtmlContent) savedInstanceState.getSerializable(STATE_KEY_HTML_QUOTE); mQuotedTextBar.setVisibility(savedInstanceState.getBoolean(STATE_KEY_QUOTED_TEXT_SHOWN) ? View.VISIBLE : View.GONE); @@ -854,6 +866,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc if (mQuotedHtmlContent != null && mQuotedHtmlContent.getQuotedContent() != null) { mQuotedHTML.loadDataWithBaseURL("http://", mQuotedHtmlContent.getQuotedContent(), "text/html", "utf-8", null); + mQuotedTextEdit.setVisibility(View.VISIBLE); } } else @@ -940,7 +953,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc // Handle HTML separate from the rest of the text content. HTML mode doesn't allow signature after the quoted // text, nor does it allow reply after quote. Users who want that functionality will need to stick with text // mode. - if (mAccount.getMessageFormat() == MessageFormat.HTML) + if (mMessageFormat == MessageFormat.HTML) { // Add the signature. if (!isDraft) @@ -1000,7 +1013,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc return body; } } - else if (mAccount.getMessageFormat() == MessageFormat.TEXT) + else if (mMessageFormat == MessageFormat.TEXT) { // Capture composed message length before we start attaching quoted parts and signatures. Integer composedMessageLength = text.length(); @@ -1097,7 +1110,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc final boolean hasAttachments = mAttachments.getChildCount() > 0; - if (mAccount.getMessageFormat() == MessageFormat.HTML) + if (mMessageFormat == MessageFormat.HTML) { // HTML message (with alternative text part) @@ -1265,7 +1278,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc uri.appendQueryParameter(IdentityField.OFFSET.value(), Integer.toString(0)); } // Save the message format for this offset. - uri.appendQueryParameter(IdentityField.MESSAGE_FORMAT.value(), mAccount.getMessageFormat().name()); + uri.appendQueryParameter(IdentityField.MESSAGE_FORMAT.value(), mMessageFormat.name()); // If we're not using the standard identity of signature, append it on to the identity blob. if (mSignatureChanged) @@ -1806,11 +1819,35 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mDraftNeedsSaving = true; break; case R.id.quoted_text_delete: - mQuotedTextBar.setVisibility(View.GONE); - mQuotedText.setVisibility(View.GONE); - mQuotedHTML.setVisibility(View.GONE); + deleteQuotedText(); mDraftNeedsSaving = true; break; + case R.id.quoted_text_edit: + mMessageFormat = MessageFormat.TEXT; + if (mMessageReference != null) // shouldn't happen... + { + // TODO - Should we check if mSourceMessageBody is already present and bypass the MessagingController call? + MessagingController.getInstance(getApplication()).addListener(mListener); + final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.accountUuid); + final String folderName = mMessageReference.folderName; + final String sourceMessageUid = mMessageReference.uid; + MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null); + } + break; + } + } + + /** + * Delete the quoted text. + */ + private void deleteQuotedText() + { + mQuotedTextBar.setVisibility(View.GONE); + mQuotedText.setVisibility(View.GONE); + mQuotedHTML.setVisibility(View.GONE); + if (mQuotedHtmlContent != null) + { + mQuotedHtmlContent.clearQuotedContent(); } } @@ -2292,7 +2329,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc // Always respect the user's current composition format preference, even if the // draft was saved in a different format. // TODO - The current implementation doesn't allow a user in HTML mode to edit a draft that wasn't saved with K9mail. - if (mAccount.getMessageFormat() == MessageFormat.HTML) + if (mMessageFormat == MessageFormat.HTML) { if (k9identity.get(IdentityField.MESSAGE_FORMAT) == null || !MessageFormat.valueOf(k9identity.get(IdentityField.MESSAGE_FORMAT)).equals(MessageFormat.HTML)) { @@ -2330,11 +2367,12 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mQuotedHTML.loadDataWithBaseURL("http://", mQuotedHtmlContent.getQuotedContent(), "text/html", "utf-8", null); mQuotedHTML.setVisibility(View.VISIBLE); mQuotedTextBar.setVisibility(View.VISIBLE); + mQuotedTextEdit.setVisibility(View.VISIBLE); } } } } - else if (mAccount.getMessageFormat() == MessageFormat.TEXT) + else if (mMessageFormat == MessageFormat.TEXT) { MessageFormat format = k9identity.get(IdentityField.MESSAGE_FORMAT) != null ? MessageFormat.valueOf(k9identity.get(IdentityField.MESSAGE_FORMAT)) @@ -2431,8 +2469,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc // If we already have mSourceMessageBody, use that. It's pre-populated if we've got crypto going on. String content = mSourceMessageBody != null ? mSourceMessageBody - : getBodyTextFromMessage(mSourceMessage, mAccount.getMessageFormat()); - if (mAccount.getMessageFormat() == MessageFormat.HTML) + : getBodyTextFromMessage(mSourceMessage, mMessageFormat); + if (mMessageFormat == MessageFormat.HTML) { // Add the HTML reply header to the top of the content. mQuotedHtmlContent = quoteOriginalHtmlMessage(mSourceMessage, content, mAccount.getQuoteStyle()); @@ -2441,13 +2479,20 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mQuotedTextBar.setVisibility(View.VISIBLE); mQuotedHTML.setVisibility(View.VISIBLE); + mQuotedTextEdit.setVisibility(View.VISIBLE); + + mQuotedText.setVisibility(View.GONE); } - else if (mAccount.getMessageFormat() == MessageFormat.TEXT) + else if (mMessageFormat == MessageFormat.TEXT) { mQuotedText.setText(quoteOriginalTextMessage(mSourceMessage, content, mAccount.getQuoteStyle())); mQuotedTextBar.setVisibility(View.VISIBLE); mQuotedText.setVisibility(View.VISIBLE); + + mQuotedHtmlContent = null; + mQuotedTextEdit.setVisibility(View.GONE); + mQuotedHTML.setVisibility(View.GONE); } } @@ -2689,7 +2734,27 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc { public void run() { - processSourceMessage(message); + // We check to see if we've previously processed the source message since this + // could be called when switching from HTML to text replies. If that happens, we + // only want to update the UI with quoted text (which picks the appropriate + // part). + if (mSourceProcessed) + { + try + { + populateUIWithQuotedMessage(); + } catch (MessagingException e) + { + // Hm, if we couldn't populate the UI after source reprocessing, let's just delete it? + deleteQuotedText(); + Log.e(K9.LOG_TAG, "Could not re-process source message; deleting quoted text to be safe.", e); + } + } + else + { + processSourceMessage(message); + mSourceProcessed = true; + } } }); }