Add button to allow editing of quoted message in HTML mode by dropping user back to text mode. Fixes issue 2959.

This commit is contained in:
Andrew Chen 2011-02-05 15:14:02 -08:00
parent 026ace509c
commit cc9d6ac5ea
12 changed files with 129 additions and 18 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

28
res/drawable/btn_edit.xml Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2007 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:state_window_focused="false" android:state_enabled="true"
android:drawable="@drawable/btn_edit_normal" />
 <item android:state_window_focused="false" android:state_enabled="false"
android:drawable="@drawable/btn_edit_disable" />
<item android:state_pressed="true"
android:drawable="@drawable/btn_edit_pressed" />
<item android:state_enabled="true" android:state_focused="true"
android:drawable="@drawable/btn_edit_selected" />
<item android:drawable="@drawable/btn_edit_normal" />
</selector>

View file

@ -213,6 +213,22 @@
android:layout_height="wrap_content"
android:layout_width="fill_parent" />
<LinearLayout
android:id="@+id/quoted_text_buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true">
<ImageButton
android:id="@+id/quoted_text_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_marginRight="8dip"
android:background="@drawable/btn_edit" />
<ImageButton
android:id="@+id/quoted_text_delete"
android:layout_width="wrap_content"
@ -221,6 +237,8 @@
android:layout_alignParentRight="true"
android:background="@drawable/btn_dialog" />
</LinearLayout>
</RelativeLayout>
<EditText

View file

@ -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:
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);
mDraftNeedsSaving = true;
break;
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);
}
}
@ -2688,8 +2733,28 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
runOnUiThread(new Runnable()
{
public void run()
{
// 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;
}
}
});
}