diff options
author | Andrew Sapperstein <asapperstein@google.com> | 2013-09-16 11:56:13 -0700 |
---|---|---|
committer | Andrew Sapperstein <asapperstein@google.com> | 2013-09-26 11:42:34 -0700 |
commit | 5c1692a5faeab220881a17a3427a8986ef874403 (patch) | |
tree | e18e2f908c449c2d21c2066cc093d4baed4a8e20 /src | |
parent | 09a4198253fe3a342a4b2868d27a29fe3686debc (diff) | |
download | android_packages_apps_UnifiedEmail-5c1692a5faeab220881a17a3427a8986ef874403.tar.gz android_packages_apps_UnifiedEmail-5c1692a5faeab220881a17a3427a8986ef874403.tar.bz2 android_packages_apps_UnifiedEmail-5c1692a5faeab220881a17a3427a8986ef874403.zip |
Initial printing support.
Needs mocks and redlines and such.
b/10712542
TODO:
Logos for Email and Gmail.
Attachment support.
Use offscreen webview.
Secure conversation view support.
Change-Id: Iec37a9a46e506ccf12fbbb775c1b47b08a0d9724
Diffstat (limited to 'src')
15 files changed, 457 insertions, 97 deletions
diff --git a/src/com/android/mail/FormattedDateBuilder.java b/src/com/android/mail/FormattedDateBuilder.java index e53b10c90..d7c17b27c 100644 --- a/src/com/android/mail/FormattedDateBuilder.java +++ b/src/com/android/mail/FormattedDateBuilder.java @@ -58,7 +58,7 @@ public class FormattedDateBuilder { } } - private CharSequence formatLongDayAndDate(long when) { + public CharSequence formatLongDayAndDate(long when) { sb.setLength(0); DateUtils.formatDateRange(mContext, dateFormatter, when, when, DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY @@ -66,7 +66,7 @@ public class FormattedDateBuilder { return sb.toString(); } - private CharSequence formatLongTime(long when) { + public CharSequence formatLongTime(long when) { sb.setLength(0); DateUtils.formatDateRange(mContext, dateFormatter, when, when, DateUtils.FORMAT_SHOW_TIME); diff --git a/src/com/android/mail/browse/EmlMessageViewFragment.java b/src/com/android/mail/browse/EmlMessageViewFragment.java index ed357cf91..ab9c59c4b 100644 --- a/src/com/android/mail/browse/EmlMessageViewFragment.java +++ b/src/com/android/mail/browse/EmlMessageViewFragment.java @@ -19,6 +19,7 @@ package com.android.mail.browse; import android.app.Fragment; import android.app.LoaderManager; +import android.content.Context; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; @@ -236,6 +237,11 @@ public class EmlMessageViewFragment extends Fragment return mAccountUri; } + @Override + public Context getContext() { + return getActivity().getApplicationContext(); + } + // End SecureConversationViewControllerCallbacks private class MessageLoadCallbacks diff --git a/src/com/android/mail/browse/MessageCursor.java b/src/com/android/mail/browse/MessageCursor.java index 5a4146a7b..8437d8748 100644 --- a/src/com/android/mail/browse/MessageCursor.java +++ b/src/com/android/mail/browse/MessageCursor.java @@ -73,6 +73,10 @@ public class MessageCursor extends ObjectCursor<ConversationMessage> { return m; } + public Conversation getConversation() { + return mController != null ? mController.getConversation() : null; + } + // Is the conversation starred? public boolean isConversationStarred() { int pos = -1; diff --git a/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java b/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java index 92a4f3cd1..62099fcfc 100644 --- a/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java +++ b/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java @@ -19,15 +19,16 @@ package com.android.mail.browse; import android.app.AlertDialog; import android.app.Dialog; +import android.app.DialogFragment; import android.content.Context; import android.os.Bundle; -import android.app.DialogFragment; import android.view.LayoutInflater; import android.view.View; import com.android.mail.R; import com.android.mail.providers.Account; import com.android.mail.providers.Address; +import com.android.mail.utils.Utils; import java.util.HashMap; import java.util.Map; @@ -93,7 +94,7 @@ public class MessageHeaderDetailsDialogFragment extends DialogFragment { private static void addAddressesToBundle( Bundle addresses, Map<String, Address> addressCache, String[] emails) { for (final String email : emails) { - addresses.putParcelable(email, MessageHeaderView.getAddress(addressCache, email)); + addresses.putParcelable(email, Utils.getAddress(addressCache, email)); } } diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java index ed47bf51d..1c3aa3351 100644 --- a/src/com/android/mail/browse/MessageHeaderView.java +++ b/src/com/android/mail/browse/MessageHeaderView.java @@ -495,23 +495,7 @@ public class MessageHeaderView extends LinearLayout implements OnClickListener, } public Address getAddress(String emailStr) { - return getAddress(mAddressCache, emailStr); - } - - public static Address getAddress(Map<String, Address> cache, String emailStr) { - Address addr = null; - synchronized (cache) { - if (cache != null) { - addr = cache.get(emailStr); - } - if (addr == null) { - addr = Address.getEmailAddress(emailStr); - if (cache != null) { - cache.put(emailStr, addr); - } - } - } - return addr; + return Utils.getAddress(mAddressCache, emailStr); } private void updateSpacerHeight() { @@ -758,7 +742,7 @@ public class MessageHeaderView extends LinearLayout implements OnClickListener, final int len = Math.min(maxToCopy, rawAddrs.length); boolean first = true; for (int i = 0; i < len; i++) { - final Address email = getAddress(mAddressCache, rawAddrs[i]); + final Address email = Utils.getAddress(mAddressCache, rawAddrs[i]); final String emailAddress = email.getAddress(); final String name; if (mMatcher != null && mMatcher.isVeiledAddress(emailAddress)) { @@ -1326,7 +1310,7 @@ public class MessageHeaderView extends LinearLayout implements OnClickListener, } final String[] formattedEmails = new String[emails.length]; for (int i = 0; i < emails.length; i++) { - final Address email = getAddress(addressCache, emails[i]); + final Address email = Utils.getAddress(addressCache, emails[i]); String name = email.getName(); final String address = email.getAddress(); // Check if the address here is a veiled address. If it is, we need to display an diff --git a/src/com/android/mail/print/HtmlPrintTemplates.java b/src/com/android/mail/print/HtmlPrintTemplates.java new file mode 100644 index 000000000..27dfba352 --- /dev/null +++ b/src/com/android/mail/print/HtmlPrintTemplates.java @@ -0,0 +1,124 @@ +/** + * Copyright (C) 2013 Google Inc. + * Licensed to 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. + */ + +package com.android.mail.print; + +import android.content.Context; +import android.content.res.Resources; + +import com.android.mail.R; +import com.android.mail.ui.AbstractHtmlTemplates; +import com.android.mail.utils.LogTag; +import com.android.mail.utils.LogUtils; + +/** + * Renders data into very simple string-substitution HTML templates for printing conversations. + */ +public class HtmlPrintTemplates extends AbstractHtmlTemplates { + + private static final String TAG = LogTag.getLogTag(); + + private final String mConversationUpper; + private final String mMessage; + private final String mConversationLower; + private final String mConversationLowerNoJs; + + public HtmlPrintTemplates(Context context) { + super(context); + + mConversationUpper = readTemplate(R.raw.template_print_conversation_upper); + mMessage = readTemplate(R.raw.template_print_message); + mConversationLower = readTemplate(R.raw.template_print_conversation_lower); + mConversationLowerNoJs = readTemplate(R.raw.template_print_conversation_lower_no_js); + } + + /** + * Start building the html for a printed conversation. Can only be called once + * until {@link #endPrintConversation()} or {@link #endPrintConversationNoJavascript()} + * is called. + */ + public void startPrintConversation(String accountName, String accountAddress, + String subject, int numMessages) { + if (mInProgress) { + throw new IllegalStateException("Should not call startPrintConversation twice"); + } + + reset(); + + final Resources res = mContext.getResources(); + final String numMessageString = res.getQuantityString( + R.plurals.num_messages, numMessages, numMessages); + append(mConversationUpper, mContext.getString(R.string.app_name), + accountName == null ? "" : accountName, + accountAddress, subject, numMessageString); + + mInProgress = true; + } + + /** + * Add a message to the html for this printed conversation. + */ + public void appendMessage(String senderName, String senderAddress, String date, + String recipients, String bodyHtml, String attachments) { + append(mMessage, senderName, senderAddress, date, recipients, bodyHtml, attachments); + } + + /** + * Adds the end of the printed conversation to the html. NOTE: this method + * includes JavaScript. If you need a version without JavaScript, + * use {@link #endPrintConversationNoJavascript()}.<br/><br/> + * + * One example where we use JavaScript is to hide quoted text. + * + * @return a {@link String} containing the html for the conversation. + */ + public String endPrintConversation() { + if (!mInProgress) { + throw new IllegalStateException("must call startConversation first"); + } + + append(mConversationLower, mContext.getString(R.string.quoted_text_hidden_print)); + + mInProgress = false; + + LogUtils.d(TAG, "rendered conversation of %d bytes, buffer capacity=%d", + mBuilder.length() << 1, mBuilder.capacity() << 1); + + return emit(); + } + + /** + * Adds the end of the printed conversation to the html. NOTE: this method + * does not include any JavaScript. If you need a version with JavaScript, + * use {@link #endPrintConversation()}. + * @return a {@link String} containing the html for the conversation. + */ + public String endPrintConversationNoJavascript() { + if (!mInProgress) { + throw new IllegalStateException("must call startConversation first"); + } + + append(mConversationLowerNoJs); + + mInProgress = false; + + LogUtils.d(TAG, "rendered conversation of %d bytes, buffer capacity=%d", + mBuilder.length() << 1, mBuilder.capacity() << 1); + + return emit(); + } +} diff --git a/src/com/android/mail/print/Printer.java b/src/com/android/mail/print/Printer.java new file mode 100644 index 000000000..7744c37ca --- /dev/null +++ b/src/com/android/mail/print/Printer.java @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2013 Google Inc. + * Licensed to 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. + */ + +package com.android.mail.print; + +import android.content.Context; +import android.content.res.Resources; +import android.text.TextUtils; + +import com.android.mail.FormattedDateBuilder; +import com.android.mail.R; +import com.android.mail.browse.ConversationMessage; +import com.android.mail.browse.MessageCursor; +import com.android.mail.providers.Account; +import com.android.mail.providers.Address; +import com.android.mail.providers.Conversation; +import com.android.mail.providers.UIProvider; +import com.android.mail.utils.Utils; + +import java.util.Map; + +/** + * Static class that provides a {@link #print} function to build a print html document. + */ +public class Printer { + private static final String DIV_START = "<div>"; + private static final String REPLY_TO_DIV_START = "<div class=\"replyto\">"; + private static final String DIV_END = "</div>"; + + /** + * Builds an html document that is suitable for printing and returns it as a {@link String}. + */ + public static String print(Context context, Account account, + MessageCursor cursor, Map<String, Address> addressCache, boolean useJavascript) { + final HtmlPrintTemplates templates = new HtmlPrintTemplates(context); + final FormattedDateBuilder dateBuilder = new FormattedDateBuilder(context); + + if (!cursor.moveToFirst()) { + throw new IllegalStateException("trying to print without a conversation"); + } + + // TODO - remove account name(not account.name which is email address) or get it somehow + final Conversation conversation = cursor.getConversation(); + templates.startPrintConversation("", account.name, + conversation.subject, conversation.getNumMessages()); + + // for each message in the conversation, add message html + final Resources res = context.getResources(); + do { + final ConversationMessage message = cursor.getMessage(); + final Address fromAddress = Utils.getAddress(addressCache, message.getFrom()); + final long when = message.dateReceivedMs; + final String date = res.getString(R.string.date_message_received_print, + dateBuilder.formatLongDayAndDate(when), dateBuilder.formatLongTime(when)); + + + templates.appendMessage(fromAddress.getName(), fromAddress.getAddress(), date, + renderRecipients(res, addressCache, message), message.getBodyAsHtml(), + ""); // TODO - attachment html + } while (cursor.moveToNext()); + + // only include JavaScript if specifically requested + return useJavascript ? + templates.endPrintConversation() : templates.endPrintConversationNoJavascript(); + } + + /** + * Builds html for the message header. Specifically, the (optional) lists of + * reply-to, to, cc, and bcc. + */ + private static String renderRecipients(Resources res, Map<String, Address> addressCache, + ConversationMessage message) { + final StringBuilder recipients = new StringBuilder(); + + // reply-to + final String replyTo = renderEmailList(res, message.getReplyToAddresses(), addressCache); + buildEmailDiv(res, recipients, replyTo, REPLY_TO_DIV_START, DIV_END, + R.string.replyto_heading); + + // to + // To has special semantics since the message can be a draft. + // If it is a draft and there are no to addresses, we just print "Draft". + // If it is a draft and there are to addresses, we print "Draft To: " + // If not a draft, we just use "To: ". + final boolean isDraft = message.draftType != UIProvider.DraftType.NOT_A_DRAFT; + final String to = renderEmailList(res, message.getToAddresses(), addressCache); + if (isDraft && to == null) { + recipients.append(DIV_START).append(res.getString(R.string.draft_heading)) + .append(DIV_END); + } else { + buildEmailDiv(res, recipients, to, DIV_START, DIV_END, + isDraft ? R.string.draft_to_heading : R.string.to_heading); + } + + // cc + final String cc = renderEmailList(res, message.getCcAddresses(), addressCache); + buildEmailDiv(res, recipients, cc, DIV_START, DIV_END, + R.string.cc_heading); + + // bcc + final String bcc = renderEmailList(res, message.getBccAddresses(), addressCache); + buildEmailDiv(res, recipients, bcc, DIV_START, DIV_END, + R.string.bcc_heading); + + return recipients.toString(); + } + + /** + * Appends an html div containing a list of emails based on the passed in data. + */ + private static void buildEmailDiv(Resources res, StringBuilder recipients, String emailList, + String divStart, String divEnd, int headingId) { + if (emailList != null) { + recipients.append(divStart).append(res.getString(headingId)) + .append(emailList).append(divEnd); + } + } + + /** + * Builds and returns a list of comma-separated emails of the form "Name <email>". + * If the email does not contain a name, "email" is used instead. + */ + private static String renderEmailList(Resources resources, String[] emails, + Map<String, Address> addressCache) { + if (emails == null || emails.length == 0) { + return null; + } + final String[] formattedEmails = new String[emails.length]; + for (int i = 0; i < emails.length; i++) { + final Address email = Utils.getAddress(addressCache, emails[i]); + final String name = email.getName(); + final String address = email.getAddress(); + + if (TextUtils.isEmpty(name)) { + formattedEmails[i] = address; + } else { + formattedEmails[i] = resources.getString(R.string.address_print_display_format, + name, address); + } + } + + return TextUtils.join(", ", formattedEmails); + } +} diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java index 00234037b..473d1588d 100644 --- a/src/com/android/mail/ui/AbstractConversationViewFragment.java +++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Loader; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.view.Menu; @@ -326,6 +327,9 @@ public abstract class AbstractConversationViewFragment extends Fragment implemen } else if (itemId == R.id.show_original) { showUntransformedConversation(); handled = true; + } else if (itemId == R.id.print) { + printConversation(); + handled = true; } return handled; } @@ -335,6 +339,7 @@ public abstract class AbstractConversationViewFragment extends Fragment implemen // Only show option if we support message transforms and message has been transformed. Utils.setMenuItemVisibility(menu, R.id.show_original, supportsMessageTransforms() && mHasConversationBeenTransformed && !mHasConversationTransformBeenReverted); + Utils.setMenuItemVisibility(menu, R.id.print, Utils.isRunningKitkatOrLater()); } abstract boolean supportsMessageTransforms(); @@ -634,4 +639,6 @@ public abstract class AbstractConversationViewFragment extends Fragment implemen return (mAccount.enableMessageTransforms > 0) && !mHasConversationTransformBeenReverted; } + + protected abstract void printConversation(); } diff --git a/src/com/android/mail/ui/AbstractHtmlTemplates.java b/src/com/android/mail/ui/AbstractHtmlTemplates.java new file mode 100644 index 000000000..25c3bc50b --- /dev/null +++ b/src/com/android/mail/ui/AbstractHtmlTemplates.java @@ -0,0 +1,95 @@ +/** + * Copyright (C) 2013 Google Inc. + * Licensed to 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. + */ + +package com.android.mail.ui; + +import android.content.Context; +import android.content.res.Resources; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Formatter; + +/** + * Abstract class to support common functionality for both + * {@link com.android.mail.ui.HtmlConversationTemplates} and + * {@link com.android.mail.print.HtmlPrintTemplates}. + * + * Renders data into very simple string-substitution HTML templates. + * + * Templates should be UTF-8 encoded HTML with '%s' placeholders to be substituted upon render. + * Plain-jane string substitution with '%s' is slightly faster than typed substitution. + */ +public abstract class AbstractHtmlTemplates { + // TODO: refine. too expensive to iterate over cursor and pre-calculate total. so either + // estimate it, or defer assembly until the end when size is known (deferring increases + // working set size vs. estimation but is exact). + private static final int BUFFER_SIZE_CHARS = 64 * 1024; + + protected Context mContext; + protected Formatter mFormatter; + protected StringBuilder mBuilder; + protected boolean mInProgress = false; + + public AbstractHtmlTemplates(Context context) { + mContext = context; + } + + public String emit() { + final String out = mFormatter.toString(); + // release the builder memory ASAP + mFormatter = null; + mBuilder = null; + return out; + } + + public void reset() { + mBuilder = new StringBuilder(BUFFER_SIZE_CHARS); + mFormatter = new Formatter(mBuilder, null /* no localization */); + } + + protected String readTemplate(int id) throws Resources.NotFoundException { + final StringBuilder out = new StringBuilder(); + InputStreamReader in = null; + try { + try { + in = new InputStreamReader( + mContext.getResources().openRawResource(id), "UTF-8"); + final char[] buf = new char[4096]; + int chars; + + while ((chars=in.read(buf)) > 0) { + out.append(buf, 0, chars); + } + + return out.toString(); + + } finally { + if (in != null) { + in.close(); + } + } + } catch (IOException e) { + throw new Resources.NotFoundException("Unable to open template id=" + + Integer.toHexString(id) + " exception=" + e.getMessage()); + } + } + + protected void append(String template, Object... args) { + mFormatter.format(template, args); + } +} diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java index e850d4896..51484b195 100644 --- a/src/com/android/mail/ui/ConversationViewFragment.java +++ b/src/com/android/mail/ui/ConversationViewFragment.java @@ -27,6 +27,9 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; import android.os.SystemClock; +import android.print.PrintAttributes; +import android.print.PrintJob; +import android.print.PrintManager; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.ScaleGestureDetector; @@ -63,6 +66,7 @@ import com.android.mail.browse.ScrollIndicatorsView; import com.android.mail.browse.SuperCollapsedBlock; import com.android.mail.browse.WebViewContextMenu; import com.android.mail.content.ObjectCursor; +import com.android.mail.print.Printer; import com.android.mail.providers.Account; import com.android.mail.providers.Address; import com.android.mail.providers.Conversation; @@ -1574,4 +1578,17 @@ public class ConversationViewFragment extends AbstractConversationViewFragment i } } + + protected void printConversation() { + // TODO - offscreen webview stuff so that we don't clobber + final String convHtml = + Printer.print(getContext(), mAccount, getMessageCursor(), + mAddressCache, true /* userJavascript */); + mWebView.loadDataWithBaseURL(mBaseUri, convHtml, "text/html", "utf-8", null); + final PrintManager printManager = + (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE); + printManager.print(getConversation().subject, + mWebView.createPrintDocumentAdapter(), + new PrintAttributes.Builder().build()); + } } diff --git a/src/com/android/mail/ui/HtmlConversationTemplates.java b/src/com/android/mail/ui/HtmlConversationTemplates.java index d368454d3..104d0c03e 100644 --- a/src/com/android/mail/ui/HtmlConversationTemplates.java +++ b/src/com/android/mail/ui/HtmlConversationTemplates.java @@ -1,4 +1,4 @@ -/* +/** * Copyright (C) 2012 Google Inc. * Licensed to The Android Open Source Project. * @@ -18,7 +18,6 @@ package com.android.mail.ui; import android.content.Context; -import android.content.res.Resources.NotFoundException; import com.android.mail.R; import com.android.mail.utils.LogTag; @@ -26,30 +25,17 @@ import com.android.mail.utils.LogUtils; import com.android.mail.utils.Utils; import com.google.common.annotations.VisibleForTesting; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Formatter; import java.util.regex.Pattern; /** * Renders data into very simple string-substitution HTML templates for conversation view. - * - * Templates should be UTF-8 encoded HTML with '%s' placeholders to be substituted upon render. - * Plain-jane string substitution with '%s' is slightly faster than typed substitution. - * */ -public class HtmlConversationTemplates { +public class HtmlConversationTemplates extends AbstractHtmlTemplates { /** * Prefix applied to a message id for use as a div id */ public static final String MESSAGE_PREFIX = "m"; - public static final int MESSAGE_PREFIX_LENGTH = MESSAGE_PREFIX.length(); - - // TODO: refine. too expensive to iterate over cursor and pre-calculate total. so either - // estimate it, or defer assembly until the end when size is known (deferring increases - // working set size vs. estimation but is exact). - private static final int BUFFER_SIZE_CHARS = 64 * 1024; private static final String TAG = LogTag.getLogTag(); @@ -92,13 +78,8 @@ public class HtmlConversationTemplates { private static String sConversationUpper; private static String sConversationLower; - private Context mContext; - private Formatter mFormatter; - private StringBuilder mBuilder; - private boolean mInProgress = false; - public HtmlConversationTemplates(Context context) { - mContext = context; + super(context); // The templates are small (~2KB total in ICS MR2), so it's okay to load them once and keep // them in memory. @@ -178,7 +159,8 @@ public class HtmlConversationTemplates { public void startConversation(int sideMargin, int conversationHeaderHeight) { if (mInProgress) { - throw new IllegalStateException("must call startConversation first"); + throw new IllegalStateException( + "Should not call start conversation until end conversation has been called"); } reset(); @@ -209,49 +191,4 @@ public class HtmlConversationTemplates { return emit(); } - - public String emit() { - String out = mFormatter.toString(); - // release the builder memory ASAP - mFormatter = null; - mBuilder = null; - return out; - } - - public void reset() { - mBuilder = new StringBuilder(BUFFER_SIZE_CHARS); - mFormatter = new Formatter(mBuilder, null /* no localization */); - } - - private String readTemplate(int id) throws NotFoundException { - StringBuilder out = new StringBuilder(); - InputStreamReader in = null; - try { - try { - in = new InputStreamReader( - mContext.getResources().openRawResource(id), "UTF-8"); - char[] buf = new char[4096]; - int chars; - - while ((chars=in.read(buf)) > 0) { - out.append(buf, 0, chars); - } - - return out.toString(); - - } finally { - if (in != null) { - in.close(); - } - } - } catch (IOException e) { - throw new NotFoundException("Unable to open template id=" + Integer.toHexString(id) - + " exception=" + e.getMessage()); - } - } - - private void append(String template, Object... args) { - mFormatter.format(template, args); - } - } diff --git a/src/com/android/mail/ui/SecureConversationViewController.java b/src/com/android/mail/ui/SecureConversationViewController.java index 1f9b13e87..4a89bd292 100644 --- a/src/com/android/mail/ui/SecureConversationViewController.java +++ b/src/com/android/mail/ui/SecureConversationViewController.java @@ -183,6 +183,10 @@ public class SecureConversationViewController implements mConversationHeaderView.setSubject(subject); } + public void printConversation() { + // TODO - implement this + } + // Start MessageHeaderViewCallbacks implementations @Override diff --git a/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java b/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java index 2e4f5d97e..0284a494d 100644 --- a/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java +++ b/src/com/android/mail/ui/SecureConversationViewControllerCallbacks.java @@ -18,6 +18,7 @@ package com.android.mail.ui; import android.app.Fragment; +import android.content.Context; import android.net.Uri; import android.os.Handler; @@ -46,4 +47,5 @@ public interface SecureConversationViewControllerCallbacks { public String getBaseUri(); public boolean isViewOnlyMode(); public Uri getAccountUri(); + public Context getContext(); } diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java index 14937b788..729a77480 100644 --- a/src/com/android/mail/ui/SecureConversationViewFragment.java +++ b/src/com/android/mail/ui/SecureConversationViewFragment.java @@ -261,4 +261,8 @@ public class SecureConversationViewFragment extends AbstractConversationViewFrag public boolean supportsMessageTransforms() { return false; } + + protected void printConversation() { + mViewController.printConversation(); + } } diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java index 8286befdc..e6a0312d3 100644 --- a/src/com/android/mail/utils/Utils.java +++ b/src/com/android/mail/utils/Utils.java @@ -16,6 +16,7 @@ package com.android.mail.utils; +import com.android.mail.providers.Address; import com.google.android.mail.common.html.parser.HtmlDocument; import com.google.android.mail.common.html.parser.HtmlParser; import com.google.android.mail.common.html.parser.HtmlTree; @@ -726,7 +727,7 @@ public class Utils { /** * Create an intent to show a conversation. * @param conversation Conversation to open. - * @param folder + * @param folderUri * @param account * @return */ @@ -749,7 +750,7 @@ public class Utils { /** * Create an intent to open a folder. * - * @param folder Folder to open. + * @param folderUri Folder to open. * @param account * @return */ @@ -1043,8 +1044,8 @@ public class Utils { * * @param type MIME data type to normalize * @return normalized MIME data type, or null if the input was null - * @see {@link #setType} - * @see {@link #setTypeAndNormalize} + * @see {@link android.content.Intent#setType} + * @see {@link android.content.Intent#setTypeAndNormalize} */ public static String normalizeMimeType(String type) { if (type == null) { @@ -1061,7 +1062,7 @@ public class Utils { } /** - * (copied from {@link Uri#normalize()} for pre-J) + * (copied from {@link android.net.Uri#normalizeScheme()} for pre-J) * * Return a normalized representation of this Uri. * @@ -1083,7 +1084,7 @@ public class Utils { * * @return normalized Uri (never null) * @see {@link android.content.Intent#setData} - * @see {@link #setNormalizedData} + * @see {@link android.content.Intent#setNormalizedData} */ public static Uri normalizeUri(Uri uri) { String scheme = uri.getScheme(); @@ -1429,4 +1430,20 @@ public class Utils { } } + + public static Address getAddress(Map<String, Address> cache, String emailStr) { + Address addr = null; + synchronized (cache) { + if (cache != null) { + addr = cache.get(emailStr); + } + if (addr == null) { + addr = Address.getEmailAddress(emailStr); + if (cache != null) { + cache.put(emailStr, addr); + } + } + } + return addr; + } } |