Merge "Add another getMessages() api to Folder" into jb-ub-mail-ur10
diff --git a/Android.mk b/Android.mk
index 1cf0bb6..84f7b45 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,7 +19,8 @@
#Include res dir from photoviewer
photo_dir := ../../../frameworks/opt/photoviewer/res
-res_dirs := $(chips_dir) $(photo_dir) res
+res_dirs := res $(chips_dir) $(photo_dir)
+
##################################################
# Build APK
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a615fac..febfebc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -42,7 +42,7 @@
android:label="@string/app_name"
android:name=".ui.MailActivity"
android:launchMode="singleTop"
- android:uiOptions="splitActionBarWhenNarrow">
+ android:theme="@style/PlainUnifiedEmailTheme" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -123,6 +123,14 @@
</activity>
<provider
+ android:authorities="com.android.mail.accountcache"
+ android:label="@string/account_cache_provider"
+ android:multiprocess="false"
+ android:name=".providers.UnifiedAccountCacheProvider" >
+ <grant-uri-permission android:pathPattern=".*" />
+ </provider>
+
+ <provider
android:authorities="com.android.mail.mockprovider"
android:label="@string/mock_content_provider"
android:multiprocess="false"
@@ -139,14 +147,6 @@
</provider>
<provider
- android:authorities="com.android.mail.accountcache"
- android:label="@string/account_cache_provider"
- android:multiprocess="false"
- android:name=".providers.UnifiedAccountCacheProvider" >
- <grant-uri-permission android:pathPattern=".*" />
- </provider>
-
- <provider
android:authorities="@string/eml_attachment_provider"
android:multiprocess="false"
android:exported="false"
diff --git a/proguard.flags b/proguard.flags
index 5d90442..0699881 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -61,6 +61,10 @@
-keepclasseswithmembers class com.android.mail.browse.ConversationItemView {
*** setAnimatedHeightFraction(...);
*** setAnimatedProgressFraction(...);
+ *** setAnimatedFadeFraction0(...);
+ *** setAnimatedFadeFraction1(...);
+ *** setPhotoFlipFraction(...);
+ *** setPeekIconFlipFraction(...);
}
-keepclasseswithmembers class com.android.mail.ui.MailActivity {
diff --git a/res/drawable-hdpi/ic_avatar_check.png b/res/drawable-hdpi/ic_avatar_check.png
new file mode 100644
index 0000000..e904f7d
--- /dev/null
+++ b/res/drawable-hdpi/ic_avatar_check.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_star_off.png b/res/drawable-hdpi/ic_btn_star_off.png
new file mode 100644
index 0000000..85481fe
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_star_off.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_btn_star_on.png b/res/drawable-hdpi/ic_btn_star_on.png
new file mode 100644
index 0000000..4654ef5
--- /dev/null
+++ b/res/drawable-hdpi/ic_btn_star_on.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_peak_eye.png b/res/drawable-hdpi/ic_peak_eye.png
new file mode 100644
index 0000000..ee2238d
--- /dev/null
+++ b/res/drawable-hdpi/ic_peak_eye.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_off.png b/res/drawable-hdpi/ic_star_off.png
deleted file mode 100644
index cf1cd90..0000000
--- a/res/drawable-hdpi/ic_star_off.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_off_convo_view_holo_light.png b/res/drawable-hdpi/ic_star_off_convo_view_holo_light.png
index 8289a76..c119657 100644
--- a/res/drawable-hdpi/ic_star_off_convo_view_holo_light.png
+++ b/res/drawable-hdpi/ic_star_off_convo_view_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_on.png b/res/drawable-hdpi/ic_star_on.png
deleted file mode 100644
index b694bbb..0000000
--- a/res/drawable-hdpi/ic_star_on.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_star_on_convo_view_holo_light.png b/res/drawable-hdpi/ic_star_on_convo_view_holo_light.png
index 544b076..d180107 100644
--- a/res/drawable-hdpi/ic_star_on_convo_view_holo_light.png
+++ b/res/drawable-hdpi/ic_star_on_convo_view_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_avatar_check.png b/res/drawable-mdpi/ic_avatar_check.png
new file mode 100644
index 0000000..1224199
--- /dev/null
+++ b/res/drawable-mdpi/ic_avatar_check.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_star_off.png b/res/drawable-mdpi/ic_btn_star_off.png
new file mode 100644
index 0000000..0add19a
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_star_off.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_btn_star_on.png b/res/drawable-mdpi/ic_btn_star_on.png
new file mode 100644
index 0000000..54a4230
--- /dev/null
+++ b/res/drawable-mdpi/ic_btn_star_on.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_peak_eye.png b/res/drawable-mdpi/ic_peak_eye.png
new file mode 100644
index 0000000..40e15fa
--- /dev/null
+++ b/res/drawable-mdpi/ic_peak_eye.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_off.png b/res/drawable-mdpi/ic_star_off.png
deleted file mode 100644
index 522b5ab..0000000
--- a/res/drawable-mdpi/ic_star_off.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_off_convo_view_holo_light.png b/res/drawable-mdpi/ic_star_off_convo_view_holo_light.png
index d01da9f..1b63df6 100644
--- a/res/drawable-mdpi/ic_star_off_convo_view_holo_light.png
+++ b/res/drawable-mdpi/ic_star_off_convo_view_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_on.png b/res/drawable-mdpi/ic_star_on.png
deleted file mode 100644
index 50dd679..0000000
--- a/res/drawable-mdpi/ic_star_on.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_star_on_convo_view_holo_light.png b/res/drawable-mdpi/ic_star_on_convo_view_holo_light.png
index 683258e..32d878e 100644
--- a/res/drawable-mdpi/ic_star_on_convo_view_holo_light.png
+++ b/res/drawable-mdpi/ic_star_on_convo_view_holo_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_avatar_check.png b/res/drawable-xhdpi/ic_avatar_check.png
new file mode 100644
index 0000000..6bc3d92
--- /dev/null
+++ b/res/drawable-xhdpi/ic_avatar_check.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_btn_star_off.png b/res/drawable-xhdpi/ic_btn_star_off.png
new file mode 100644
index 0000000..eb5cbe2
--- /dev/null
+++ b/res/drawable-xhdpi/ic_btn_star_off.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_btn_star_on.png b/res/drawable-xhdpi/ic_btn_star_on.png
new file mode 100644
index 0000000..9751701
--- /dev/null
+++ b/res/drawable-xhdpi/ic_btn_star_on.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_peak_eye.png b/res/drawable-xhdpi/ic_peak_eye.png
new file mode 100644
index 0000000..3054b58
--- /dev/null
+++ b/res/drawable-xhdpi/ic_peak_eye.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_off.png b/res/drawable-xhdpi/ic_star_off.png
deleted file mode 100644
index a611a1f..0000000
--- a/res/drawable-xhdpi/ic_star_off.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_off_convo_view_holo_light.png b/res/drawable-xhdpi/ic_star_off_convo_view_holo_light.png
index 23fe0ba..a401383 100644
--- a/res/drawable-xhdpi/ic_star_off_convo_view_holo_light.png
+++ b/res/drawable-xhdpi/ic_star_off_convo_view_holo_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_on.png b/res/drawable-xhdpi/ic_star_on.png
deleted file mode 100644
index f77acd7..0000000
--- a/res/drawable-xhdpi/ic_star_on.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_star_on_convo_view_holo_light.png b/res/drawable-xhdpi/ic_star_on_convo_view_holo_light.png
index e54a509..a3a39d2 100644
--- a/res/drawable-xhdpi/ic_star_on_convo_view_holo_light.png
+++ b/res/drawable-xhdpi/ic_star_on_convo_view_holo_light.png
Binary files differ
diff --git a/res/layout/ad_header_view.xml b/res/layout/ad_header_view.xml
new file mode 100644
index 0000000..1ed6c27
--- /dev/null
+++ b/res/layout/ad_header_view.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<com.android.mail.ads.AdHeaderView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ad_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/ad_background_yellow"
+ android:orientation="vertical"
+ android:paddingTop="@dimen/conversation_header_vertical_padding"
+ android:paddingBottom="@dimen/conversation_header_vertical_padding"
+ android:layout_marginStart="@dimen/conversation_view_margin_side"
+ android:layout_marginEnd="@dimen/conversation_view_margin_side"
+ android:layout_marginLeft="@dimen/conversation_view_margin_side"
+ android:layout_marginRight="@dimen/conversation_view_margin_side" >
+
+ <TextView
+ android:id="@+id/ad_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|right"
+ android:background="?android:attr/selectableItemBackground"
+ android:gravity="center_vertical"
+ android:paddingStart="@dimen/conversation_header_side_padding"
+ android:paddingEnd="@dimen/conversation_header_side_padding"
+ android:paddingLeft="@dimen/conversation_header_side_padding"
+ android:paddingRight="@dimen/conversation_header_side_padding"
+ android:text="@string/ads"
+ android:textAllCaps="true"
+ android:textColor="@color/conv_header_text_dark"
+ android:drawableEnd="@drawable/ic_alert_grey"
+ android:drawableRight="@drawable/ic_alert_grey"
+ />
+
+ <TextView
+ android:id="@+id/ad_subject"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/conversation_header_vertical_item_padding"
+ android:paddingStart="@dimen/conversation_header_side_padding"
+ android:paddingEnd="@dimen/conversation_header_side_padding"
+ android:paddingLeft="@dimen/conversation_header_side_padding"
+ android:paddingRight="@dimen/conversation_header_side_padding"
+ android:includeFontPadding="false"
+ style="@style/ConversationSubjectStyle" />
+
+</com.android.mail.ads.AdHeaderView>
diff --git a/res/layout/conversation_item_view_normal.xml b/res/layout/conversation_item_view_normal.xml
index 149dca0..b75de04 100644
--- a/res/layout/conversation_item_view_normal.xml
+++ b/res/layout/conversation_item_view_normal.xml
@@ -35,14 +35,6 @@
android:layout_marginRight="16dp"
android:orientation="horizontal">
- <ImageView
- android:id="@+id/checkmark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="12dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/btn_check_on_normal_holo_light" />
-
<View
android:id="@+id/contact_image"
android:layout_width="48dp"
@@ -144,12 +136,14 @@
android:id="@+id/star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/subject"
android:layout_alignParentRight="true"
+ android:layout_marginBottom="6dp"
android:layout_marginTop="-1dp"
- android:src="@drawable/ic_star_off" />
+ android:src="@drawable/ic_btn_star_off" />
<TextView
- android:id="@+id/subject"
+ android:id="@id/subject"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/star"
@@ -177,12 +171,12 @@
android:layout_marginBottom="12dp"
android:visibility="gone" />
- <!-- Folders should be 0dp below the subject, so we cancel out the 12dp bottom margin above -->
+ <!-- Folders should be 10dp below the subject, so we cancel out part of the 12dp bottom margin above -->
<TextView
android:id="@+id/folders"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="-12dp"
+ android:layout_marginTop="-2dp"
android:fontFamily="sans-serif-light"
android:includeFontPadding="false"
android:text="@string/long_string"
diff --git a/res/layout/conversation_item_view_normal_spacious.xml b/res/layout/conversation_item_view_normal_spacious.xml
index 25218e6..10e34e0 100644
--- a/res/layout/conversation_item_view_normal_spacious.xml
+++ b/res/layout/conversation_item_view_normal_spacious.xml
@@ -35,14 +35,6 @@
android:layout_marginRight="16dp"
android:orientation="horizontal">
- <ImageView
- android:id="@+id/checkmark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="16dp"
- android:layout_gravity="center_vertical"
- android:src="@drawable/btn_check_on_normal_holo_light" />
-
<View
android:id="@+id/contact_image"
android:layout_width="48dp"
@@ -144,9 +136,11 @@
android:id="@+id/star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_alignBottom="@+id/subject"
android:layout_alignParentRight="true"
+ android:layout_marginBottom="6dp"
android:layout_marginTop="-1dp"
- android:src="@drawable/ic_star_off" />
+ android:src="@drawable/ic_btn_star_off" />
<TextView
android:id="@+id/subject"
@@ -180,12 +174,12 @@
android:layout_marginBottom="16dp"
android:visibility="gone" />
- <!-- Labels should be 0dp below the subject, so we cancel out the 16dp bottom margin -->
+ <!-- Labels should be 10dp below the subject, so we cancel out part of the 16dp bottom margin -->
<TextView
android:id="@+id/folders"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="-16dp"
+ android:layout_marginTop="-6dp"
android:fontFamily="sans-serif-light"
android:includeFontPadding="false"
android:text="@string/long_string"
diff --git a/res/layout/conversation_item_view_wide.xml b/res/layout/conversation_item_view_wide.xml
index 6061e21..04a0d48 100644
--- a/res/layout/conversation_item_view_wide.xml
+++ b/res/layout/conversation_item_view_wide.xml
@@ -44,13 +44,6 @@
android:minHeight="66dp"
android:gravity="center_vertical">
- <ImageView
- android:id="@+id/checkmark"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="20dp"
- android:src="@drawable/btn_check_on_normal_holo_light" />
-
<View
android:id="@+id/contact_image"
android:layout_width="46dp"
@@ -135,14 +128,14 @@
android:includeFontPadding="false"
android:text="@string/date" />
- <!-- align to date -->
+ <!-- align to bottom of subject text -->
<ImageView
android:id="@+id/star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="-1dp"
+ android:layout_marginTop="2dp"
android:layout_marginLeft="32dp"
- android:src="@drawable/ic_star_off" />
+ android:src="@drawable/ic_btn_star_off" />
</LinearLayout>
diff --git a/res/layout/conversation_message_details_header.xml b/res/layout/conversation_message_details_header.xml
index 505f24f..172bbd2 100644
--- a/res/layout/conversation_message_details_header.xml
+++ b/res/layout/conversation_message_details_header.xml
@@ -26,9 +26,10 @@
android:paddingRight="@dimen/message_details_header_padding_end" >
<TextView
android:id="@+id/recipients_summary"
+ android:layout_width="0dp"
android:layout_gravity="fill_horizontal"
- android:layout_marginEnd="16dip"
- android:layout_marginRight="16dip"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
android:singleLine="true"
android:bufferType="spannable"
style="@style/MessageHeaderSmallStyle" />
diff --git a/res/layout/conversation_message_details_header_expanded.xml b/res/layout/conversation_message_details_header_expanded.xml
index 8381edf..a5aa753 100644
--- a/res/layout/conversation_message_details_header_expanded.xml
+++ b/res/layout/conversation_message_details_header_expanded.xml
@@ -47,7 +47,6 @@
android:layout_marginBottom="4dp"
android:layout_column="1"
android:layout_row="0"
- android:autoLink="email"
android:visibility="gone"
style="@style/MessageDetailsValueStyle" />
<ImageView
@@ -80,7 +79,6 @@
android:layout_marginBottom="4dp"
android:layout_column="1"
android:layout_row="1"
- android:autoLink="email"
android:visibility="gone"
style="@style/MessageDetailsValueStyle" />
<TextView
@@ -103,7 +101,6 @@
android:layout_marginBottom="4dp"
android:layout_column="1"
android:layout_row="2"
- android:autoLink="email"
android:visibility="gone"
style="@style/MessageDetailsValueStyle" />
<TextView
@@ -126,7 +123,6 @@
android:layout_marginBottom="4dp"
android:layout_column="1"
android:layout_row="3"
- android:autoLink="email"
android:visibility="gone"
style="@style/MessageDetailsValueStyle" />
<TextView
@@ -149,7 +145,6 @@
android:layout_marginBottom="4dp"
android:layout_column="1"
android:layout_row="4"
- android:autoLink="email"
android:visibility="gone"
style="@style/MessageDetailsValueStyle" />
diff --git a/res/layout/conversation_photo_teaser_view.xml b/res/layout/conversation_photo_teaser_view.xml
index dd6b9f6..46318f9 100644
--- a/res/layout/conversation_photo_teaser_view.xml
+++ b/res/layout/conversation_photo_teaser_view.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2013 Google Inc. -->
-<com.google.android.gm.ui.GmailConversationPhotoTeaserView
+<com.android.mail.ui.ConversationPhotoTeaserView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -59,4 +59,4 @@
android:src="@drawable/ic_cancel_holo_light" />
</LinearLayout>
-</com.google.android.gm.ui.GmailConversationPhotoTeaserView>
\ No newline at end of file
+</com.android.mail.ui.ConversationPhotoTeaserView>
\ No newline at end of file
diff --git a/res/menu-sw600dp/compose_menu.xml b/res/menu-sw600dp/compose_menu.xml
index aef2382..5377bce 100644
--- a/res/menu-sw600dp/compose_menu.xml
+++ b/res/menu-sw600dp/compose_menu.xml
@@ -27,6 +27,11 @@
android:title="@string/save_draft"
android:alphabeticShortcut="@string/trigger_save_char" />
+ <item android:id="@+id/add_photo_attachment"
+ android:icon="@drawable/ic_attachment_holo_light"
+ android:title="@string/add_photo_attachment"
+ android:showAsAction="never" />
+
<item android:id="@+id/add_video_attachment"
android:icon="@drawable/ic_attachment_holo_light"
android:title="@string/add_video_attachment"
diff --git a/res/menu-sw600dp/general_prefs_fragment_menu.xml b/res/menu-sw600dp/general_prefs_fragment_menu.xml
index 37b73f2..bd4627f 100644
--- a/res/menu-sw600dp/general_prefs_fragment_menu.xml
+++ b/res/menu-sw600dp/general_prefs_fragment_menu.xml
@@ -19,11 +19,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
- android:id="@+id/add_new_account"
- android:title="@string/add_account"
- android:showAsAction="ifRoom|withText" />
-
- <item
android:id="@+id/clear_picture_approvals_menu_item"
android:showAsAction="never"
android:title="@string/clear_display_images_whitelist_title"/>
diff --git a/res/menu-sw600dp/settings_fragment_menu.xml b/res/menu-sw600dp/settings_fragment_menu.xml
index afff6a9..a39e681 100644
--- a/res/menu-sw600dp/settings_fragment_menu.xml
+++ b/res/menu-sw600dp/settings_fragment_menu.xml
@@ -19,11 +19,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
- android:id="@+id/add_new_account"
- android:title="@string/add_account"
- android:showAsAction="ifRoom|withText" />
-
- <item
android:id="@+id/feedback_menu_item"
android:icon="@android:drawable/ic_menu_send"
android:title="@string/feedback" />
diff --git a/res/menu/settings_menu.xml b/res/menu/settings_menu.xml
index 4129ba2..a39e681 100644
--- a/res/menu/settings_menu.xml
+++ b/res/menu/settings_menu.xml
@@ -19,11 +19,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
- android:id="@+id/add_new_account"
- android:title="@string/add_account"
- android:showAsAction="always" />
-
- <item
android:id="@+id/feedback_menu_item"
android:icon="@android:drawable/ic_menu_send"
android:title="@string/feedback" />
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 37213d0..bfeb6ca 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"gesprek ongelees"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Konsep"</item>
<item quantity="other" msgid="6961049507579977505">"Konsepte"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Vou ontvanger se details in"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Wys kontakinligting vir <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Wys kontakinligting"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> ouer boodskappe"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Van:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Antwoord aan:"</string>
<string name="to_heading" msgid="3219994961726691756">"Aan:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Vouer-ikoon"</string>
<string name="add_account" msgid="2162808366829269770">"Voeg rekening by"</string>
<string name="attached_message" msgid="4267189489654642035">"Heg boodskap aan"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Vandag <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Gister <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Advertensies"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index dc03846..4e1de69 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"ያልተነበበ ውይይት"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"ረቂቅ"</item>
<item quantity="other" msgid="6961049507579977505">"ረቂቆች"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"የተቀባይ ዝርዝሮች ሰብስብ"</string>
<string name="contact_info_string" msgid="6911322458329265644">"የ<xliff:g id="NAME">%1$s</xliff:g> የእውቂያ መረጃ አሳይ"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"የዕውቂያ መረጃ አሳይ"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"ቀን፦"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> የቆዩ መልዕክቶች"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"ከ፦"</string>
<string name="replyto_heading" msgid="2081358811894701297">"መልስ ለ፦"</string>
<string name="to_heading" msgid="3219994961726691756">"ለ፦"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"የአቃፊ አዶ"</string>
<string name="add_account" msgid="2162808366829269770">"መለያ ያክሉ"</string>
<string name="attached_message" msgid="4267189489654642035">"የተያያዘ መልዕክት"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>፣ <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"ዛሬ፣ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"ትላንት፣ <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"ማስታወቂያዎች"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index d630d9b..4058f61 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"لم تتم قراءة المحادثة"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"مسودة"</item>
<item quantity="other" msgid="6961049507579977505">"مسودات"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"تصغير تفاصيل المستلم"</string>
<string name="contact_info_string" msgid="6911322458329265644">"عرض معلومات جهة الاتصال لـ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"عرض معلومات جهة الاتصال"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"التاريخ:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"الرسائل القديمة: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"من:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"جهة الرد:"</string>
<string name="to_heading" msgid="3219994961726691756">"إلى:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"رمز المجلد"</string>
<string name="add_account" msgid="2162808366829269770">"إضافة حساب"</string>
<string name="attached_message" msgid="4267189489654642035">"الرسالة المرفقة"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"اليوم، <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"أمس، <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"الإعلانات"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index f6a4682..4aca629 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -255,8 +255,7 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Згарнуць дадзеныя пра атрымальніка"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Паказаць кантактную інфармацыю карыстальнiка <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Паказаць кантактную інфармацыю"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Дата:"</string>
+ <!-- no translation found for show_messages_read:other (7439716291751085801) -->
<string name="from_heading" msgid="8950294114718418954">"Ад:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Адказаць:"</string>
<string name="to_heading" msgid="3219994961726691756">"Каму:"</string>
@@ -429,4 +428,12 @@
<!-- no translation found for add_account (2162808366829269770) -->
<skip />
<string name="attached_message" msgid="4267189489654642035">"Прымацаванае паведамленне"</string>
+ <!-- no translation found for date_message_received (6302308934790266050) -->
+ <skip />
+ <!-- no translation found for date_message_received_today (7923108495669251362) -->
+ <skip />
+ <!-- no translation found for date_message_received_yesterday (2240669381396206434) -->
+ <skip />
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 84e8f54..0f1ae32 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"кореспонденцията не е прочетена"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+ <xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Чернова"</item>
<item quantity="other" msgid="6961049507579977505">"Чернови"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Свиване на подробностите за получателя"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Показване на информацията за връзка със: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Показване на информацията за връзка"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Дата:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> по-стари съобщения"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"От:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Отг. до:"</string>
<string name="to_heading" msgid="3219994961726691756">"До:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Икона на папката"</string>
<string name="add_account" msgid="2162808366829269770">"Добавяне на профил"</string>
<string name="attached_message" msgid="4267189489654642035">"Прикачено съобщение"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Днес, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Вчера, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Реклами"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index dfd88d6..dbc7cc8 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversa per llegir"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Esborrany"</item>
<item quantity="other" msgid="6961049507579977505">"Esborranys"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Redueix les dades del destinatari"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostra la informació de contacte de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostra la informació de contacte"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> missatges anteriors"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Respon a:"</string>
<string name="to_heading" msgid="3219994961726691756">"Per a:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Icona de la carpeta"</string>
<string name="add_account" msgid="2162808366829269770">"Afegeix un compte"</string>
<string name="attached_message" msgid="4267189489654642035">"Missatge adjunt"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Avui a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ahir a les <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anuncis"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 07a02d9..7f17295 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"Konverzace nebyla přečtena."</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Koncept"</item>
<item quantity="other" msgid="6961049507579977505">"Koncepty"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Sbalit podrobnosti o příjemci"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Zobrazit kontaktní údaje uživatele <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Zobrazit kontaktní údaje"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Starší zprávy: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Odesílatel:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Odpovědět:"</string>
<string name="to_heading" msgid="3219994961726691756">"Komu:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikona složky"</string>
<string name="add_account" msgid="2162808366829269770">"Přidat účet"</string>
<string name="attached_message" msgid="4267189489654642035">"Přiložená zpráva"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Dnes v <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Včera v <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Reklamy"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index da5cac0..d92a607 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"samtalen er ulæst"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Kladde"</item>
<item quantity="other" msgid="6961049507579977505">"Kladder"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Skjul modtageroplysninger"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Vis kontaktoplysninger for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Vis kontaktoplysninger"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Dato:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> ældre beskeder"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Fra:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Svar til:"</string>
<string name="to_heading" msgid="3219994961726691756">"Til:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mappeikon"</string>
<string name="add_account" msgid="2162808366829269770">"Tilføj konto"</string>
<string name="attached_message" msgid="4267189489654642035">"Vedhæftet meddelelse"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"I dag kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"I går kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Annoncer"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7548d3d..73b8edb 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"Konversation ungelesen"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+ <xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Entwurf"</item>
<item quantity="other" msgid="6961049507579977505">"Entwürfe"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Empfängerdetails minimieren"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Kontaktinformationen für <xliff:g id="NAME">%1$s</xliff:g> anzeigen"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Kontaktinformationen anzeigen"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> ältere Nachrichten"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Von:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Antwort:"</string>
<string name="to_heading" msgid="3219994961726691756">"An:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ordnersymbol"</string>
<string name="add_account" msgid="2162808366829269770">"Konto hinzufügen"</string>
<string name="attached_message" msgid="4267189489654642035">"Angehängte Nachricht"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> um <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Heute um <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Gestern um <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anzeigen"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 923fd78..6d68c4a 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"μη αναγνωσμένη συνομιλία"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Πρόχειρο"</item>
<item quantity="other" msgid="6961049507579977505">"Πρόχειρα"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Σύμπτυξη στοιχείων παραλήπτη"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Εμφάνιση στοιχείων επικοινωνίας για τον χρήστη <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Εμφάνιση στοιχείων επικοινωνίας"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Ημ/νία:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> παλαιότερα μηνύματα"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Από:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Απάντ. σε:"</string>
<string name="to_heading" msgid="3219994961726691756">"Προς:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Εικονίδιο φακέλου"</string>
<string name="add_account" msgid="2162808366829269770">"Προσθήκη λογαριασμού"</string>
<string name="attached_message" msgid="4267189489654642035">"Συνημμένο μήνυμα"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Σήμερα, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Χθες, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Διαφημίσεις"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 31cac60..bc6ff1d 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversation unread"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Draft"</item>
<item quantity="other" msgid="6961049507579977505">"Drafts"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Collapse recipient details"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Show contact information for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Show contact information"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Date:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> older messages"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"From:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Reply to:"</string>
<string name="to_heading" msgid="3219994961726691756">"To:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Folder icon"</string>
<string name="add_account" msgid="2162808366829269770">"Add account"</string>
<string name="attached_message" msgid="4267189489654642035">"Attached message"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Today, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Yesterday, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Ads"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 7804b7d..bc2a623 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversación no leída"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Borrador"</item>
<item quantity="other" msgid="6961049507579977505">"Borradores"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Contraer detalles del destinatario"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostrar la información de contacto de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostrar la información de contacto"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Fecha:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> mensajes antiguos"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Responder a:"</string>
<string name="to_heading" msgid="3219994961726691756">"Para:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ícono de carpeta"</string>
<string name="add_account" msgid="2162808366829269770">"Agregar cuenta"</string>
<string name="attached_message" msgid="4267189489654642035">"Mensaje adjunto"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hoy, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ayer, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 46b0af5..62726ad 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversación no leída"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Borrador"</item>
<item quantity="other" msgid="6961049507579977505">"Borradores"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Contraer información del destinatario"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostrar información de contacto de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostrar información de contacto"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Fecha:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> mensajes antiguos"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Responder a:"</string>
<string name="to_heading" msgid="3219994961726691756">"Para:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Icono de carpeta"</string>
<string name="add_account" msgid="2162808366829269770">"Añadir cuenta"</string>
<string name="attached_message" msgid="4267189489654642035">"Mensaje adjunto"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hoy a las <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ayer a las <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anuncios"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 63be8f0..001ee1c 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"lugemata vestlus"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>] <xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Mustand"</item>
<item quantity="other" msgid="6961049507579977505">"Mustandid"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Ahenda saaja üksikasjad"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Kuva saatja <xliff:g id="NAME">%1$s</xliff:g> kontaktandmed"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Kuva kontaktandmed"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Kuupäev:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> vanemat sõnumit"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Saatja:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Vasta:"</string>
<string name="to_heading" msgid="3219994961726691756">"Saaja:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Kausta ikoon"</string>
<string name="add_account" msgid="2162808366829269770">"Lisa konto"</string>
<string name="attached_message" msgid="4267189489654642035">"Lisatud sõnum"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Täna kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Eile kell <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Reklaamid"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 8b5c7dc..5d4e506 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"مکالمه خوانده نشده است"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"پیشنویس"</item>
<item quantity="other" msgid="6961049507579977505">"پیشنویسها"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"کوچک کردن جزئیات گیرنده"</string>
<string name="contact_info_string" msgid="6911322458329265644">"نمایش اطلاعات تماس برای <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"نمایش اطلاعات مخاطب"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"تاریخ:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> پیام قدیمیتر"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"از:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"پاسخ به:"</string>
<string name="to_heading" msgid="3219994961726691756">"گیرنده:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"نماد پوشه"</string>
<string name="add_account" msgid="2162808366829269770">"افزودن حساب"</string>
<string name="attached_message" msgid="4267189489654642035">"پیام پیوست شده"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>، <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"امروز، <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"دیروز، <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"آگهیها"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 5213d17..cec6c5f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"keskustelua ei ole luettu"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g>–<xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Luonnos"</item>
<item quantity="other" msgid="6961049507579977505">"Luonnokset"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Tiivistä vastaanottajan tiedot"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Näytä henkilön <xliff:g id="NAME">%1$s</xliff:g> yhteystiedot"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Näytä yhteystiedot"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Pvm.:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> vanhempaa viestiä"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Lähettäjä:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Vastausos.:"</string>
<string name="to_heading" msgid="3219994961726691756">"Vast.ott:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Kansiokuvake"</string>
<string name="add_account" msgid="2162808366829269770">"Lisää tili"</string>
<string name="attached_message" msgid="4267189489654642035">"Liitetty viesti"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Tänään klo <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Eilen klo <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Mainokset"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 893926d..e6df3be 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversation non lue"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Brouillon"</item>
<item quantity="other" msgid="6961049507579977505">"Brouillons"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Réduire les coordonnées du destinataire"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Afficher les coordonnées de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Afficher les coordonnées de l\'expéditeur"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Date :"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> messages plus anciens"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De :"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Adresse de réponse :"</string>
<string name="to_heading" msgid="3219994961726691756">"À :"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Icône Dossier"</string>
<string name="add_account" msgid="2162808366829269770">"Ajouter un compte"</string>
<string name="attached_message" msgid="4267189489654642035">"Message joint"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Aujourd\'hui à <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Hier à <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Annonces"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 32564c2..0ce09e0 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"वार्तालाप नहीं पढ़ा गया"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"ड्रॉफ़्ट"</item>
<item quantity="other" msgid="6961049507579977505">"ड्राफ़्ट"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"प्राप्तकर्ता जानकारी संक्षिप्त करें"</string>
<string name="contact_info_string" msgid="6911322458329265644">"<xliff:g id="NAME">%1$s</xliff:g> की संपर्क जानकारी दिखाएं"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"संपर्क जानकारी दिखाएं"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"दिनांक:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> पुराने संदेश"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"प्रेषक:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"उत्तर पता:"</string>
<string name="to_heading" msgid="3219994961726691756">"प्रति:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"फ़ोल्डर आइकन"</string>
<string name="add_account" msgid="2162808366829269770">"खाता जोड़ें"</string>
<string name="attached_message" msgid="4267189489654642035">"अनुलग्न किया गया संदेश"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"आज, <xliff:g id="TIME">%1$s</xliff:g> बजे"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"कल, <xliff:g id="TIME">%1$s</xliff:g> बजे"</string>
+ <string name="ads" msgid="8547072743610267481">"विज्ञापन"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 1e8e118..60ec871 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"razgovor nije pročitan"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Skica"</item>
<item quantity="other" msgid="6961049507579977505">"Skice"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Sažmi podatke o primatelju"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Prikaži podatke o kontaktu za <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Prikaži podatke o kontaktu"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Broj starijih poruka: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Šalje:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Prima:"</string>
<string name="to_heading" msgid="3219994961726691756">"Primatelj:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikona mape"</string>
<string name="add_account" msgid="2162808366829269770">"Dodaj račun"</string>
<string name="attached_message" msgid="4267189489654642035">"Poruka u privitku"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> u <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Danas u <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Jučer u <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Oglasi"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 04c4b59..667fd90 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"a beszélgetés nincs elolvasva"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> -- <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Piszkozat"</item>
<item quantity="other" msgid="6961049507579977505">"Piszkozatok"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Címzett adatainak elrejtése"</string>
<string name="contact_info_string" msgid="6911322458329265644">"<xliff:g id="NAME">%1$s</xliff:g> elérhetőségi adatainak megjelenítése"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Névjegyinformációk megjelenítése"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Dátum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> régebbi üzenet"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Feladó:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Válaszcím:"</string>
<string name="to_heading" msgid="3219994961726691756">"Címzett:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mappa ikon"</string>
<string name="add_account" msgid="2162808366829269770">"Fiók hozzáadása"</string>
<string name="attached_message" msgid="4267189489654642035">"Csatolt üzenetek"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Ma, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Tegnap, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Hirdetések"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0fb132c..627c50e 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"percakapan belum dibaca"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Draf"</item>
<item quantity="other" msgid="6961049507579977505">"Draf"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Ciutkan detail penerima"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Tampilkan informasi kontak untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Tampilkan informasi kontak"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Tanggal:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> pesan lebih lama"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Dari:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Balas-ke:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kepada:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikon folder"</string>
<string name="add_account" msgid="2162808366829269770">"Tambahkan akun"</string>
<string name="attached_message" msgid="4267189489654642035">"Pesan terlampir"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hari ini, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Kemarin, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Iklan"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 926a759..0faba73 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversazione da leggere"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Bozza"</item>
<item quantity="other" msgid="6961049507579977505">"Bozze"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Comprimi i dettagli destinatario"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostra informazioni di contatto di <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostra informazioni di contatto"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> messaggi meno recenti"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Da:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Rispondi a:"</string>
<string name="to_heading" msgid="3219994961726691756">"A:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Icona cartella"</string>
<string name="add_account" msgid="2162808366829269770">"Aggiungi account"</string>
<string name="attached_message" msgid="4267189489654642035">"Messaggio allegato"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Oggi alle <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ieri alle <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Annunci"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 9df0fe1..f4108f6 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"השיחה לא נקראה"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"טיוטה"</item>
<item quantity="other" msgid="6961049507579977505">"טיוטות"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"כווץ את פרטי הנמען"</string>
<string name="contact_info_string" msgid="6911322458329265644">"הצג פרטי איש קשר של <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"הצג פרטי איש קשר"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"תאריך:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> הודעות ישנות יותר"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"מ:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"השב ל:"</string>
<string name="to_heading" msgid="3219994961726691756">"אל:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"סמל תיקיה"</string>
<string name="add_account" msgid="2162808366829269770">"הוסף חשבון"</string>
<string name="attached_message" msgid="4267189489654642035">"הודעה מצורפת"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"היום ב-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"אתמול ב-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"מודעות"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index b11c6fd..fddeb5b 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"未読のスレッド"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"下書き"</item>
<item quantity="other" msgid="6961049507579977505">"下書き"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"受信者の詳細を隠す"</string>
<string name="contact_info_string" msgid="6911322458329265644">"<xliff:g id="NAME">%1$s</xliff:g>の連絡先情報を表示"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"連絡先情報を表示"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"日付:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"これ以前のメッセージ<xliff:g id="COUNT">%1$d</xliff:g>件"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"From:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"返信先:"</string>
<string name="to_heading" msgid="3219994961726691756">"To:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"フォルダアイコン"</string>
<string name="add_account" msgid="2162808366829269770">"アカウントを追加"</string>
<string name="attached_message" msgid="4267189489654642035">"添付のメッセージ"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>、<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"今日、<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"昨日、<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"広告"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index e95fc11..5224cf8 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"대화 읽지 않음"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"임시보관"</item>
<item quantity="other" msgid="6961049507579977505">"임시보관함"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"수신자 세부정보 접기"</string>
<string name="contact_info_string" msgid="6911322458329265644">"<xliff:g id="NAME">%1$s</xliff:g>님에 대한 연락처 정보 표시"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"연락처 정보 표시"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"날짜:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"이전 메일 <xliff:g id="COUNT">%1$d</xliff:g>개"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"보낸사람:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"답장:"</string>
<string name="to_heading" msgid="3219994961726691756">"받는사람:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"폴더 아이콘"</string>
<string name="add_account" msgid="2162808366829269770">"계정 추가"</string>
<string name="attached_message" msgid="4267189489654642035">"첨부된 메시지"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"오늘 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"어제 <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"광고"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 0db9ad0..68911f7 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"pokalbis neskaitytas"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g>–<xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Juodraštis"</item>
<item quantity="other" msgid="6961049507579977505">"Juodrašč."</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Sutraukti išsamią gavėjo informaciją"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Rodyti <xliff:g id="NAME">%1$s</xliff:g> kontaktinę informaciją"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Rodyti kontaktinę informaciją"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Senesnių pranešimų: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Nuo:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Atsakyti:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kam:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Aplanko piktograma"</string>
<string name="add_account" msgid="2162808366829269770">"Pridėti paskyrą"</string>
<string name="attached_message" msgid="4267189489654642035">"Pridėtas pranešimas"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Šiandien <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Vakar <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Skelbimai"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index d55fdf1..5180c9b 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"saruna nav izlasīta"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Melnraksts"</item>
<item quantity="other" msgid="6961049507579977505">"Melnraksti"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Sakļaut informāciju par adresātu"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Rādīt sūtītāja <xliff:g id="NAME">%1$s</xliff:g> kontaktinformāciju"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Rādīt kontaktinformāciju"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datums:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> vecāki ziņojumi"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"No:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Atbildēt:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kam:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mapes ikona"</string>
<string name="add_account" msgid="2162808366829269770">"Pievienot kontu"</string>
<string name="attached_message" msgid="4267189489654642035">"Pievienots ziņojums"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, plkst. <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Šodien plkst. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Vakar plkst. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Reklāmas"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index c1957a6..d5fcae6 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"perbualan belum dibaca"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Draf"</item>
<item quantity="other" msgid="6961049507579977505">"Draf"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Runtuhkan butiran penerima"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Papar maklumat kenalan untuk <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Tunjukkan maklumat kenalan"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Tarikh:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> mesej lebih lama"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Daripada:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Balas-kpd:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kepada:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikon folder"</string>
<string name="add_account" msgid="2162808366829269770">"Tambah akaun"</string>
<string name="attached_message" msgid="4267189489654642035">"Mesej lampiran"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hari ini, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Semalam, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Iklan"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 3a1ba72..09c2e76 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"samtalen er ulest"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Utkast"</item>
<item quantity="other" msgid="6961049507579977505">"Utkast"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Skjul detaljer om mottaker"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Vis kontaktinformasjon for <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Vis kontaktinformasjon"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Dato:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> eldre e-poster"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Fra:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Svar til:"</string>
<string name="to_heading" msgid="3219994961726691756">"Til:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mappeikon"</string>
<string name="add_account" msgid="2162808366829269770">"Legg til konto"</string>
<string name="attached_message" msgid="4267189489654642035">"Vedlagt e-post"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"I dag kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"I går kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Annonser"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 47f91d2..3758c5c 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -35,7 +35,7 @@
<item msgid="4085029907540221568">"Allen beantwoorden"</item>
<item msgid="857480048798815437">"Doorsturen"</item>
</string-array>
- <string name="reply_attribution" msgid="717207316577386788">"Op <xliff:g id="DATE">%s</xliff:g> schreef <xliff:g id="PERSON">%s</xliff:g> het volgende:"</string>
+ <string name="reply_attribution" msgid="717207316577386788">"Op <xliff:g id="DATE">%s</xliff:g> schreef <xliff:g id="PERSON">%s</xliff:g>:"</string>
<string name="forward_attribution" msgid="1498936339458535158">"---------- Doorgestuurd bericht ----------<br>Van: <xliff:g id="FROM">%1$s</xliff:g><br>Datum: <xliff:g id="DATE">%2$s</xliff:g><br>Onderwerp: <xliff:g id="SUBJECT">%3$s</xliff:g><br>Aan: <xliff:g id="TO">%4$s</xliff:g><br>"</string>
<string name="cc_attribution" msgid="374493748526504562">"Cc: <xliff:g id="CC">%1$s</xliff:g><br>"</string>
<string name="select_attachment_type" msgid="4711524151968942082">"Bijlagetype selecteren"</string>
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversatie ongelezen"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Concept"</item>
<item quantity="other" msgid="6961049507579977505">"Concepten"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Ontvangersdetails samenvouwen"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Contactgegevens weergeven voor <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Contactgegevens weergeven"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> oudere berichten"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Van:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Antwoord:"</string>
<string name="to_heading" msgid="3219994961726691756">"Aan:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mappictogram"</string>
<string name="add_account" msgid="2162808366829269770">"Account toevoegen"</string>
<string name="attached_message" msgid="4267189489654642035">"Bijgevoegd bericht"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Vandaag, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Gisteren, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Advertenties"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 76ac987..5754b91 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -162,8 +162,7 @@
<string name="unread_string" msgid="588180203444398297">"wątek nie został przeczytany"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Wersja robocza"</item>
<item quantity="other" msgid="6961049507579977505">"Wersje robocze"</item>
@@ -251,8 +250,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Zwiń szczegóły odbiorcy"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Pokaż informacje kontaktowe: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Pokaż informacje kontaktowe"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Starsze wiadomości: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Od:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Odp. do:"</string>
<string name="to_heading" msgid="3219994961726691756">"Do:"</string>
@@ -423,4 +423,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikona folderu"</string>
<string name="add_account" msgid="2162808366829269770">"Dodaj konto"</string>
<string name="attached_message" msgid="4267189489654642035">"Dołączona wiadomość"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Dzisiaj, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Wczoraj, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Reklamy"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index d0d933f..c4ae6bb 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversa não lida"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Rascunho"</item>
<item quantity="other" msgid="6961049507579977505">"Rascunhos"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Fechar detalhes do destinatário"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostrar informações de contacto de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostrar informações de contacto"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> mensagens mais antigas"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Responder a:"</string>
<string name="to_heading" msgid="3219994961726691756">"Para:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ícone de pasta"</string>
<string name="add_account" msgid="2162808366829269770">"Adicionar conta"</string>
<string name="attached_message" msgid="4267189489654642035">"Mensagem anexada"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hoje às <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ontem às <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anúncios"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 7779c94..7d39969 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversa não lida"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Rascunho"</item>
<item quantity="other" msgid="6961049507579977505">"Rascunhos"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Recolher detalhes do destinatário"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Mostrar informações de contato de <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Mostrar informações de contato"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Data:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> mensagens mais antigas"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Res. para:"</string>
<string name="to_heading" msgid="3219994961726691756">"Para:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ícone de pasta"</string>
<string name="add_account" msgid="2162808366829269770">"Adicionar conta"</string>
<string name="attached_message" msgid="4267189489654642035">"Mensagem anexa"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hoje, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ontem, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anúncios"</string>
</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 26b84e2..8cc17f7 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -381,9 +381,7 @@
<skip />
<!-- no translation found for contact_info_string_default (596531738469809159) -->
<skip />
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <!-- no translation found for date_heading (2414358582984879303) -->
- <skip />
+ <!-- no translation found for show_messages_read:other (7439716291751085801) -->
<!-- no translation found for from_heading (8950294114718418954) -->
<skip />
<!-- no translation found for replyto_heading (2081358811894701297) -->
@@ -656,4 +654,12 @@
<skip />
<!-- no translation found for attached_message (4267189489654642035) -->
<skip />
+ <!-- no translation found for date_message_received (6302308934790266050) -->
+ <skip />
+ <!-- no translation found for date_message_received_today (7923108495669251362) -->
+ <skip />
+ <!-- no translation found for date_message_received_yesterday (2240669381396206434) -->
+ <skip />
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index e86c9b6..6d86ba1 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"conversație necitită"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>] <xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Mesaj nefinalizat"</item>
<item quantity="other" msgid="6961049507579977505">"Mesaje nefinalizate"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Restrângeţi detaliile destinatarului"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Afişaţi informaţiile de contact pentru <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Afişaţi informaţiile de contact"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Dată:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> (de) mesaje mai vechi"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"De la:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Răsp. la:"</string>
<string name="to_heading" msgid="3219994961726691756">"Către:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Pictogramă dosar"</string>
<string name="add_account" msgid="2162808366829269770">"Adăugați un cont"</string>
<string name="attached_message" msgid="4267189489654642035">"Mesaj atașat"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Astăzi, la <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Ieri, la <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Anunțuri"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 8c2c504..32c85d6 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"не прочитано"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Черновик"</item>
<item quantity="other" msgid="6961049507579977505">"Черновики"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Скрыть сведения о получателе"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Показать контактные данные пользователя <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Показать контактные данные"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Дата:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Старых сообщений: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"От:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Ответить:"</string>
<string name="to_heading" msgid="3219994961726691756">"Кому:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Значок папки"</string>
<string name="add_account" msgid="2162808366829269770">"Добавить аккаунт"</string>
<string name="attached_message" msgid="4267189489654642035">"Прикрепленные сообщения"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Сегодня, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Вчера, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 36b6b51..f2c51d1 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"konverzácia nebola prečítaná"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Koncept"</item>
<item quantity="other" msgid="6961049507579977505">"Koncepty"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Zbaliť podrobnosti o príjemcovi"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Zobraziť informácie kontaktu <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Zobraziť kontaktné informácie"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Dátum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Počet starších správ: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Od:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Odpovedať:"</string>
<string name="to_heading" msgid="3219994961726691756">"Komu:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikona priečinka"</string>
<string name="add_account" msgid="2162808366829269770">"Pridať účet"</string>
<string name="attached_message" msgid="4267189489654642035">"Priložená správa"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> o <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Dnes o <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Včera o <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 939f13c..161dc3b 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"pogovor ni bil prebran"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Osnutek"</item>
<item quantity="other" msgid="6961049507579977505">"Osnutki"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Strni podrobnosti prejemnika"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Prikaz podatkov za stik za <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Prikaži podatke za stik"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Št. starejših sporočil: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Od:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Odgovori:"</string>
<string name="to_heading" msgid="3219994961726691756">"Za:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikona mape"</string>
<string name="add_account" msgid="2162808366829269770">"Dodaj račun"</string>
<string name="attached_message" msgid="4267189489654642035">"Pripeto sporočilo"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Danes ob <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Včeraj ob <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Oglasi"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 0d6482b..5898936 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"преписка није прочитана"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>] <xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Недовршена порука"</item>
<item quantity="other" msgid="6961049507579977505">"Недовршене поруке"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Скупи детаље о примаоцу"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Прикажи контакт информације корисника <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Прикажи контакт информације"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Датум:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Старијих порука: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Од:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Одговор на:"</string>
<string name="to_heading" msgid="3219994961726691756">"Коме:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Икона директоријума"</string>
<string name="add_account" msgid="2162808366829269770">"Додај налог"</string>
<string name="attached_message" msgid="4267189489654642035">"Приложена порука"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Данас, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Јуче, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 685a5fc..7a732f7 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"konversationen är oläst"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Utkast"</item>
<item quantity="other" msgid="6961049507579977505">"Utkast"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Komprimera mottagardetaljer"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Visa kontaktuppgifter för <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Visa kontaktuppgifter"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Datum:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> äldre meddelanden"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Från:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Svara till:"</string>
<string name="to_heading" msgid="3219994961726691756">"Till:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Mappikon"</string>
<string name="add_account" msgid="2162808366829269770">"Lägg till konto"</string>
<string name="attached_message" msgid="4267189489654642035">"Bifogat meddelande"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Idag kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"I går kl. <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Annonser"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 43b7b95..bd9c804 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"mazungumzo hayajasomwa"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Rasimu"</item>
<item quantity="other" msgid="6961049507579977505">"Rasimu"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Kunja maelezo ya wapokeaji"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Onyesha maelezo ya mawasiliano ya <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Onyesha maelezo ya mawasiliano"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Tarehe:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Ujumbe <xliff:g id="COUNT">%1$d</xliff:g> wa zamani"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Kutoka:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Jibu-kwa:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kwa:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Ikoni ya folda"</string>
<string name="add_account" msgid="2162808366829269770">"Ongeza akaunti"</string>
<string name="attached_message" msgid="4267189489654642035">"Ujumbe ulioambatishwa"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Leo, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Jana, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Matangazo"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index cf66250..d2c0255 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"ยังไม่ได้อ่านการสนทนา"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"ร่างจดหมาย"</item>
<item quantity="other" msgid="6961049507579977505">"ร่างจดหมาย"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"ยุบรายละเอียดผู้รับ"</string>
<string name="contact_info_string" msgid="6911322458329265644">"แสดงข้อมูลติดต่อของ <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"แสดงข้อมูลติดต่อ"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"วันที่:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> ข้อความเก่า"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"จาก:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"ตอบกลับ:"</string>
<string name="to_heading" msgid="3219994961726691756">"ถึง:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"ไอคอนโฟลเดอร์"</string>
<string name="add_account" msgid="2162808366829269770">"เพิ่มบัญชี"</string>
<string name="attached_message" msgid="4267189489654642035">"ข้อความที่แนบมา"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g> เวลา <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"วันนี้เวลา <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"เมื่อวานนี้เวลา <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"โฆษณา"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index e4e11ce..9cb6b4d 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"hindi pa nababasang pag-uusap"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Draft"</item>
<item quantity="other" msgid="6961049507579977505">"Mga Draft"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Tiklupin ang mga detalye ng recipient"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Ipakita ang impormasyon ng contact para kay <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Ipakita ang impormasyon ng contact"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Petsa:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> (na) mas lumang mensahe"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Mula kay:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Tugon kay:"</string>
<string name="to_heading" msgid="3219994961726691756">"Para kay:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Icon ng folder"</string>
<string name="add_account" msgid="2162808366829269770">"Magdagdag ng account"</string>
<string name="attached_message" msgid="4267189489654642035">"Naka-attach na mensahe"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Ngayon, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Kahapon, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Mga Ad"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 1aa6be8..2151a76 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"ileti dizisi okunmadı"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Taslak"</item>
<item quantity="other" msgid="6961049507579977505">"Taslaklar"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Alıcı ayrıntılarını daralt"</string>
<string name="contact_info_string" msgid="6911322458329265644">"<xliff:g id="NAME">%1$s</xliff:g> iletişim bilgilerini göster"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"İletişim bilgilerini göster"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Tarih:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> eski ileti"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Gönderen:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Yanıt Adresi:"</string>
<string name="to_heading" msgid="3219994961726691756">"Alıcı:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Klasör simgesi"</string>
<string name="add_account" msgid="2162808366829269770">"Hesap ekle"</string>
<string name="attached_message" msgid="4267189489654642035">"Ekli ileti"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Bugün, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Dün, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index a0f849e..aec4c99 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"бесіду не прочитано"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> – <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Чернетка"</item>
<item quantity="other" msgid="6961049507579977505">"Чернетки"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Згорнути дані отримувача"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Показати контактну інформацію відправника <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Показати контактну інформацію"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Дата:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"Попередні повідомлення: <xliff:g id="COUNT">%1$d</xliff:g>"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Від:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Відпов.:"</string>
<string name="to_heading" msgid="3219994961726691756">"Кому:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Значок папки"</string>
<string name="add_account" msgid="2162808366829269770">"Додати обліковий запис"</string>
<string name="attached_message" msgid="4267189489654642035">"Вкладене повідомлення"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Сьогодні, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Учора, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Оголошення"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index e61862d..a457943 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"cuộc trò chuyện chưa đọc"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Bản nháp"</item>
<item quantity="other" msgid="6961049507579977505">"Bản nháp"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Thu gọn chi tiết người nhận"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Hiển thị thông tin liên hệ cho <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Hiển thị thông tin liên hệ"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Ngày:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> thư cũ hơn"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Từ:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Trả lời"</string>
<string name="to_heading" msgid="3219994961726691756">"Đến:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Biểu tượng thư mục"</string>
<string name="add_account" msgid="2162808366829269770">"Thêm tài khoản"</string>
<string name="attached_message" msgid="4267189489654642035">"Tin nhắn đính kèm"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Hôm nay, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Hôm qua, <xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Quảng cáo"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 7d75de4..e0b3acd 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"未读会话"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>] <xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> - <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"草稿"</item>
<item quantity="other" msgid="6961049507579977505">"草稿"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"折叠收件人详细信息"</string>
<string name="contact_info_string" msgid="6911322458329265644">"显示<xliff:g id="NAME">%1$s</xliff:g>的联系人信息"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"显示联系人信息"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"日期:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g>封较早的邮件"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"发件人:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"回复:"</string>
<string name="to_heading" msgid="3219994961726691756">"收件人:"</string>
@@ -425,4 +425,9 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"文件夹图标"</string>
<string name="add_account" msgid="2162808366829269770">"添加帐户"</string>
<string name="attached_message" msgid="4267189489654642035">"附加的邮件"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>,<xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"今天<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"昨天<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <!-- no translation found for ads (8547072743610267481) -->
+ <skip />
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index dc569fe..81e25d1 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"未閱讀的會話群組"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"還有 <xliff:g id="ID_1">%d</xliff:g> 個附件"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"草稿"</item>
<item quantity="other" msgid="6961049507579977505">"草稿"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"收合收件者詳細資料"</string>
<string name="contact_info_string" msgid="6911322458329265644">"顯示 <xliff:g id="NAME">%1$s</xliff:g> 的聯絡人資訊"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"顯示聯絡人資訊"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"日期:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> 封較舊的郵件"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"寄件者:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"回覆:"</string>
<string name="to_heading" msgid="3219994961726691756">"收件者:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"資料夾圖示"</string>
<string name="add_account" msgid="2162808366829269770">"新增帳戶"</string>
<string name="attached_message" msgid="4267189489654642035">"附加的郵件"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g><xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"今天<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"昨天<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"廣告"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index b97b9c5..3141751 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -164,8 +164,7 @@
<string name="unread_string" msgid="588180203444398297">"inkulumo engafundiwe"</string>
<string name="filtered_tag" msgid="6470627954465675488">"[<xliff:g id="TAG">%1$s</xliff:g>]<xliff:g id="SUBJECT">%2$s</xliff:g>"</string>
<string name="subject_and_snippet" msgid="7884124651812798896">"<xliff:g id="ID_1">%s</xliff:g> — <xliff:g id="ID_2">%s</xliff:g>"</string>
- <!-- no translation found for ap_overflow_format (2285438422049030145) -->
- <skip />
+ <string name="ap_overflow_format" msgid="2285438422049030145">"+<xliff:g id="ID_1">%d</xliff:g>"</string>
<plurals name="draft">
<item quantity="one" msgid="333591132893648383">"Okusalungiswa"</item>
<item quantity="other" msgid="6961049507579977505">"Okusalungiswa"</item>
@@ -253,8 +252,9 @@
<string name="collapse_recipient_details" msgid="3608892454869745927">"Goqa imininingwane yomtholi"</string>
<string name="contact_info_string" msgid="6911322458329265644">"Khombisa imininingwane yokuxhumana ka-<xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="contact_info_string_default" msgid="596531738469809159">"Bonisa ulwazi loxhumana naye"</string>
- <!-- no translation found for show_messages_read:other (7344988174650303930) -->
- <string name="date_heading" msgid="2414358582984879303">"Usuku:"</string>
+ <plurals name="show_messages_read">
+ <item quantity="other" msgid="7439716291751085801">"<xliff:g id="COUNT">%1$d</xliff:g> imilayezo emidala"</item>
+ </plurals>
<string name="from_heading" msgid="8950294114718418954">"Kusuka:"</string>
<string name="replyto_heading" msgid="2081358811894701297">"Phendula-ku:"</string>
<string name="to_heading" msgid="3219994961726691756">"Kuya ku:"</string>
@@ -425,4 +425,8 @@
<string name="folder_icon_desc" msgid="1500547397347480618">"Isithonjana sefolda"</string>
<string name="add_account" msgid="2162808366829269770">"Engeza i-akhawunti"</string>
<string name="attached_message" msgid="4267189489654642035">"Umlayezo oshumekiwe"</string>
+ <string name="date_message_received" msgid="6302308934790266050">"<xliff:g id="DAY_AND_DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+ <string name="date_message_received_today" msgid="7923108495669251362">"Namhlanje, ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="date_message_received_yesterday" msgid="2240669381396206434">"Izolo, ngo-<xliff:g id="TIME">%1$s</xliff:g>"</string>
+ <string name="ads" msgid="8547072743610267481">"Izikhangiso"</string>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 21197aa..da9957f 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -32,6 +32,7 @@
<color name="date_text_color">@color/dark_gray_text_color</color>
<color name="message_info_text_color">@color/gray_text_color</color>
<color name="subject_text_color">#333333</color>
+ <color name="ap_background_color">#fff1f1f2</color>
<color name="ap_overflow_badge_color">#eeeeeeee</color>
<color name="ap_overflow_text_color">#ff4f4c4c</color>
<!-- a 'checked' item is in the conversation selection set. also the 'pressed' color. -->
@@ -128,4 +129,6 @@
<color name="collapsed_message_header_background_color">#eeeded</color>
<!-- The color of the expanded message header -->
<color name="expanded_message_header_background_color">@android:color/white</color>
+
+ <color name="ad_background_yellow">#fff8e5</color>
</resources>
diff --git a/res/values/constants.xml b/res/values/constants.xml
index 4cf9399..f0c15b5 100644
--- a/res/values/constants.xml
+++ b/res/values/constants.xml
@@ -117,10 +117,15 @@
<!-- Duration of progress bar animation for attachment previews -->
<integer name="ap_progress_animation_duration">4000</integer>
+ <!-- Duration of fade in/out animation for attachment previews -->
+ <integer name="ap_fade_animation_duration">500</integer>
<!-- Duration of placeholder pulse animation for attachment previews -->
<integer name="ap_placeholder_animation_duration">2000</integer>
<!-- Delay before showing progress bar animations for attachment previews that are loading -->
<integer name="ap_progress_animation_delay">2000</integer>
<!-- Max overflow count to show for attachment previews -->
<integer name="ap_overflow_max_count">99</integer>
+
+ <!-- Duration of the animations for entering/exiting CAB mode -->
+ <integer name="conv_item_view_cab_anim_duration">350</integer>
</resources>
diff --git a/res/values/helpcontext.xml b/res/values/helpcontext.xml
index 2538dac..a16f4b5 100644
--- a/res/values/helpcontext.xml
+++ b/res/values/helpcontext.xml
@@ -18,10 +18,8 @@
<resources>
<!-- Help context for the compose screen -->
<string name="compose_help_context" translatable="false">compose</string>
- <!-- Help context for the folder list, in one pane mode -->
- <string name="one_pane_folder_list_help_context" translatable="false">fl</string>
<!-- Help context for the wait mode -->
<string name="wait_help_context" translatable="false">wait</string>
<!-- Help context for the conversation list, and viewing the conversation (one or two pane) -->
<string name="main_help_context" translatable="false">ttl</string>
-</resources>
\ No newline at end of file
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 14263b2..e76f72c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -962,4 +962,7 @@
<!-- Shown to display the date of the message when the message was received yesterday. [CHAR LIMIT=50] -->
<string name="date_message_received_yesterday">Yesterday, <xliff:g id="time">%1$s</xliff:g></string>
+ <!-- Shown in the message ad header and in the list item for a message ad. [CHAR LIMIT=15]-->
+ <string name="ads">Ads</string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c57900e..9263316 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -283,9 +283,11 @@
</style>
<style name="MessageDetailsValueStyle" parent="MessageHeaderSmallStyle">
- <item name="android:textIsSelectable">true</item>
+ <item name="android:autoLink">email</item>
+ <item name="android:linksClickable">true</item>
<item name="android:textColor">@color/conv_header_text_light</item>
<item name="android:textColorLink">@color/conv_header_text_link_blue</item>
+ <item name="android:textIsSelectable">true</item>
</style>
<style name="MessageHeaderActionButtonStyle" parent="android:Widget.Holo.Button.Borderless">
diff --git a/src/com/android/mail/MailIntentService.java b/src/com/android/mail/MailIntentService.java
index 2fa0717..daca7a7 100644
--- a/src/com/android/mail/MailIntentService.java
+++ b/src/com/android/mail/MailIntentService.java
@@ -16,6 +16,7 @@
package com.android.mail;
import android.net.Uri;
+
import com.android.mail.utils.StorageLowState;
import android.app.IntentService;
@@ -24,6 +25,7 @@
import com.android.mail.providers.Account;
import com.android.mail.providers.Folder;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.NotificationUtils;
@@ -71,7 +73,8 @@
final Uri accountUri = intent.getParcelableExtra(Utils.EXTRA_ACCOUNT_URI);
final Uri folderUri = intent.getParcelableExtra(Utils.EXTRA_FOLDER_URI);
- NotificationUtils.resendNotifications(this, false, accountUri, folderUri);
+ NotificationUtils.resendNotifications(this, false, accountUri,
+ new FolderUri(folderUri));
} else if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
// The storage_low state is recorded centrally even though
// no handler might be present to change application state
diff --git a/src/com/android/mail/adapter/DrawerItem.java b/src/com/android/mail/adapter/DrawerItem.java
index 00f76f3..f8a819b 100644
--- a/src/com/android/mail/adapter/DrawerItem.java
+++ b/src/com/android/mail/adapter/DrawerItem.java
@@ -313,7 +313,7 @@
case VIEW_FOLDER:
// True if folder types and URIs are the same
if (currentFolder != null && mFolder != null) {
- return (mFolderType == currentType) && mFolder.uri.equals(currentFolder.uri);
+ return (mFolderType == currentType) && mFolder.equals(currentFolder);
}
return false;
case VIEW_ACCOUNT:
diff --git a/src/com/android/mail/ads/AdHeaderView.java b/src/com/android/mail/ads/AdHeaderView.java
new file mode 100644
index 0000000..f7da0ef
--- /dev/null
+++ b/src/com/android/mail/ads/AdHeaderView.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ads;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.mail.R;
+import com.android.mail.browse.ConversationViewAdapter.AdHeaderItem;
+
+public class AdHeaderView extends LinearLayout implements View.OnClickListener {
+ private TextView mAdSubjectView;
+
+ private AdHeaderItem mHeaderItem;
+
+ public AdHeaderView(Context context) {
+ super(context);
+ }
+
+ public AdHeaderView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mAdSubjectView = (TextView) findViewById(R.id.ad_subject);
+ findViewById(R.id.ad_info).setOnClickListener(this);
+ }
+
+ public void setAdSubject(final String subject) {
+ mAdSubjectView.setText(subject);
+ if (TextUtils.isEmpty(subject)) {
+ mAdSubjectView.setVisibility(GONE);
+ }
+ }
+
+ public void bind(AdHeaderItem headerItem) {
+ mHeaderItem = headerItem;
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch(view.getId()) {
+ case R.id.ad_info:
+ // TODO wire up clicking the ad info button
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/com/android/mail/ads/AdViewFragment.java b/src/com/android/mail/ads/AdViewFragment.java
new file mode 100644
index 0000000..c5b747d
--- /dev/null
+++ b/src/com/android/mail/ads/AdViewFragment.java
@@ -0,0 +1,119 @@
+/*
+ * 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.ads;
+
+import android.os.Bundle;
+
+import com.android.mail.browse.ConversationMessage;
+import com.android.mail.browse.MessageCursor;
+import com.android.mail.providers.Conversation;
+import com.android.mail.ui.ConversationViewFragment;
+import com.android.mail.ui.ConversationViewState;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
+
+public final class AdViewFragment extends ConversationViewFragment {
+
+ private static final String LOG_TAG = LogTag.getLogTag();
+
+ /**
+ * Constructor needs to be public to handle orientation changes and activity lifecycle events.
+ */
+ public AdViewFragment() {
+ super();
+ }
+
+ /**
+ * Creates a new instance of {@link AdViewFragment}, initialized
+ * to display a conversation with other parameters inherited/copied from an existing bundle,
+ * typically one created using {@link #makeBasicArgs}.
+ */
+ public static AdViewFragment newInstance(Bundle existingArgs,
+ Conversation conversation) {
+ final AdViewFragment f = new AdViewFragment();
+ final Bundle args = new Bundle(existingArgs);
+ args.putParcelable(ARG_CONVERSATION, conversation);
+ f.setArguments(args);
+ return f;
+ }
+
+ /**
+ * Populate the adapter with overlay views (message headers, super-collapsed blocks, a
+ * conversation header), and return an HTML document with spacer divs inserted for all overlays.
+ *
+ */
+ @Override
+ protected String renderMessageBodies(MessageCursor messageCursor,
+ boolean enableContentReadySignal) {
+ int pos = -1;
+
+ LogUtils.d(LOG_TAG, "IN renderMessageBodies, fragment=%s", this);
+ boolean allowNetworkImages = false;
+
+ // TODO: re-use any existing adapter item state (expanded, details expanded, show pics)
+
+ // Walk through the cursor and build up an overlay adapter as you go.
+ // Each overlay has an entry in the adapter for easy scroll handling in the container.
+ // Items are not necessarily 1:1 in cursor and adapter because of super-collapsed blocks.
+ // When adding adapter items, also add their heights to help the container later determine
+ // overlay dimensions.
+
+ // When re-rendering, prevent ConversationContainer from laying out overlays until after
+ // the new spacers are positioned by WebView.
+ mConversationContainer.invalidateSpacerGeometry();
+
+ mAdapter.clear();
+
+ // re-evaluate the message parts of the view state, since the messages may have changed
+ // since the previous render
+ final ConversationViewState prevState = mViewState;
+ mViewState = new ConversationViewState(prevState);
+
+ // N.B. the units of height for spacers are actually dp and not px because WebView assumes
+ // a pixel is an mdpi pixel, unless you set device-dpi.
+
+ // add a single conversation header item
+ final int adHeaderPos = mAdapter.addAdHeader(mConversation);
+ final int adHeaderPx = measureOverlayHeight(adHeaderPos);
+
+ mTemplates.startConversation(mWebView.screenPxToWebPx(mSideMarginPx),
+ mWebView.screenPxToWebPx(adHeaderPx));
+
+ if (messageCursor.moveToFirst()) {
+ final ConversationMessage msg = messageCursor.getMessage();
+ renderMessage(msg);
+ }
+
+ mWebView.getSettings().setBlockNetworkImage(false);
+
+ final boolean applyTransforms = shouldApplyTransforms();
+
+ // If the conversation has specified a base uri, use it here, otherwise use mBaseUri
+ return mTemplates.endConversation(mBaseUri, mConversation.getBaseUri(mBaseUri), 320,
+ mWebView.getViewportWidth(), enableContentReadySignal, isOverviewMode(mAccount),
+ applyTransforms, applyTransforms);
+ }
+
+ private void renderMessage(ConversationMessage msg) {
+ mAdapter.addAdFooter();
+
+ mTemplates.appendMessageHtml(msg, true /** expanded */, true /** showImages */,
+ 0 /** headerHeight */, 0 /** footerHeight */);
+ timerMark("rendered message");
+ }
+}
diff --git a/src/com/android/mail/browse/AttachmentProgressDialogFragment.java b/src/com/android/mail/browse/AttachmentProgressDialogFragment.java
index aef90eb..36c158c 100644
--- a/src/com/android/mail/browse/AttachmentProgressDialogFragment.java
+++ b/src/com/android/mail/browse/AttachmentProgressDialogFragment.java
@@ -40,7 +40,7 @@
final AttachmentProgressDialogFragment f = new AttachmentProgressDialogFragment();
// Supply the attachment as an argument.
- final Bundle args = new Bundle();
+ final Bundle args = new Bundle(1);
args.putParcelable(ATTACHMENT_KEY, attachment);
f.setArguments(args);
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index 2b1020b..4b05465 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -359,7 +359,7 @@
private int mCachePos;
private boolean mCachingEnabled = true;
private final NewCursorUpdateObserver mCursorUpdateObserver;
- private boolean mUpdateObserverRegistered;
+ private boolean mUpdateObserverRegistered = false;
// Ideally these two objects could be combined into a Map from
// conversationId -> position, but the cached values uses the conversation
@@ -377,8 +377,10 @@
// any updates
mCursorUpdateObserver =
new NewCursorUpdateObserver(new Handler(Looper.getMainLooper()));
- result.registerContentObserver(mCursorUpdateObserver);
- mUpdateObserverRegistered = true;
+ if (result != null) {
+ result.registerContentObserver(mCursorUpdateObserver);
+ mUpdateObserverRegistered = true;
+ }
final long start = SystemClock.uptimeMillis();
final Map<String, Integer> uriPositionMap;
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index cf15909..2e19842 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -28,14 +28,15 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.LinearGradient;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.SystemClock;
import android.text.Layout.Alignment;
import android.text.Spannable;
@@ -72,7 +73,6 @@
import com.android.mail.R.string;
import com.android.mail.browse.ConversationItemViewModel.SenderFragment;
import com.android.mail.perf.Timer;
-import com.android.mail.photo.MailPhotoViewActivity;
import com.android.mail.photomanager.AttachmentPreviewsManager;
import com.android.mail.photomanager.AttachmentPreviewsManager.AttachmentPreviewsDividedImageCanvas;
import com.android.mail.photomanager.AttachmentPreviewsManager.AttachmentPreviewsManagerCallback;
@@ -91,15 +91,18 @@
import com.android.mail.providers.UIProvider.ConversationListIcon;
import com.android.mail.providers.UIProvider.FolderType;
import com.android.mail.ui.AnimatedAdapter;
+import com.android.mail.ui.AnimatedAdapter.ConversationListListener;
import com.android.mail.ui.ControllableActivity;
import com.android.mail.ui.ConversationSelectionSet;
import com.android.mail.ui.DividedImageCanvas;
import com.android.mail.ui.DividedImageCanvas.InvalidateCallback;
+import com.android.mail.ui.ConversationSetObserver;
import com.android.mail.ui.FolderDisplayer;
import com.android.mail.ui.ImageCanvas;
import com.android.mail.ui.SwipeableItemView;
import com.android.mail.ui.SwipeableListView;
import com.android.mail.ui.ViewMode;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.HardwareLayerEnabler;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
@@ -128,6 +131,8 @@
// Static bitmaps.
private static Bitmap STAR_OFF;
private static Bitmap STAR_ON;
+ private static Bitmap PEEK;
+ private static Bitmap CHECK;
private static Bitmap ATTACHMENT;
private static Bitmap ONLY_TO_ME;
private static Bitmap TO_ME_AND_OTHERS;
@@ -148,30 +153,30 @@
private static String sOverflowCountFormat;
// Static colors.
- private static int sActivatedTextColor;
private static int sSendersTextColorRead;
private static int sSendersTextColorUnread;
private static int sDateTextColor;
+ private static int sAttachmentPreviewsBackgroundColor;
private static int sOverflowBadgeColor;
private static int sOverflowTextColor;
private static int sStarTouchSlop;
private static int sSenderImageTouchSlop;
- @Deprecated
- private static int sStandardScaledDimen;
private static int sShrinkAnimationDuration;
private static int sSlideAnimationDuration;
- private static int sAnimatingBackgroundColor;
private static int sProgressAnimationDuration;
+ private static int sFadeAnimationDuration;
private static float sPlaceholderAnimationDurationRatio;
private static int sProgressAnimationDelay;
private static Interpolator sPulseAnimationInterpolator;
private static int sOverflowCountMax;
+ private static int sCabAnimationDuration;
// Static paints.
- private static TextPaint sPaint = new TextPaint();
- private static TextPaint sFoldersPaint = new TextPaint();
+ private static final TextPaint sPaint = new TextPaint();
+ private static final TextPaint sFoldersPaint = new TextPaint();
+ private static final Paint sCheckBackgroundPaint = new Paint();
- private static Rect sRect = new Rect();
+ private static final Rect sRect = new Rect();
// Backgrounds for different states.
private final SparseArray<Drawable> mBackgrounds = new SparseArray<Drawable>();
@@ -211,16 +216,17 @@
private int mLastTouchX;
private int mLastTouchY;
private AnimatedAdapter mAdapter;
+ private int mAdapterPosition;
private float mAnimatedHeightFraction = 1.0f;
private final String mAccount;
private ControllableActivity mActivity;
+ private ConversationListListener mConversationListListener;
private final TextView mSubjectTextView;
private final TextView mSendersTextView;
private int mGadgetMode;
private final DividedImageCanvas mContactImagesHolder;
private static ContactPhotoManager sContactPhotoManager;
-
private static int sFoldersLeftPadding;
private static TextAppearanceSpan sSubjectTextUnreadSpan;
private static TextAppearanceSpan sSubjectTextReadSpan;
@@ -236,17 +242,38 @@
* this animator does not remove the progress bars.
*/
private final ObjectAnimator mProgressAnimator;
+ private final ObjectAnimator mFadeAnimator0;
+ private final ObjectAnimator mFadeAnimator1;
private long mProgressAnimatorCancelledTime;
/** Range from 0.0f to 1.0f. */
private float mAnimatedProgressFraction;
- private int[] mImagesLoaded = new int[0];
+ private float mAnimatedFadeFraction0;
+ private float mAnimatedFadeFraction1;
+ private int[] mImageLoadStatuses = new int[0];
private boolean mShowProgressBar;
- private Runnable mSetShowProgressBarRunnable;
+ private final Runnable mCancelProgressAnimatorRunnable;
+ private final Runnable mSetShowProgressBarRunnable0;
+ private final Runnable mSetShowProgressBarRunnable1;
private static final boolean CONVLIST_ATTACHMENT_PREVIEWS_ENABLED = true;
+ private final Matrix mPhotoFlipMatrix = new Matrix();
+ private final Matrix mCheckMatrix = new Matrix();
+ private final Matrix mPeekIconFlipMatrix = new Matrix();
+
+ private final CabAnimator mPhotoFlipAnimator;
+ private final CabAnimator mPeekIconFlipAnimator;
+
+ /**
+ * The conversation id, if this conversation was selected the last time we were in a selection
+ * mode. This is reset after any animations complete upon exiting the selection mode.
+ */
+ private long mLastSelectedId = -1;
+
static {
sPaint.setAntiAlias(true);
sFoldersPaint.setAntiAlias(true);
+
+ sCheckBackgroundPaint.setColor(Color.GRAY);
}
public static void setScrollStateChanged(final int scrollState) {
@@ -281,7 +308,7 @@
}
@Override
- public void loadConversationFolders(Conversation conv, final Uri ignoreFolderUri,
+ public void loadConversationFolders(Conversation conv, final FolderUri ignoreFolderUri,
final int ignoreFolderType) {
super.loadConversationFolders(conv, ignoreFolderUri, ignoreFolderType);
mFoldersCount = mFoldersSortedSet.size();
@@ -325,7 +352,6 @@
final int xEnd = coordinates.foldersXEnd;
final int y = coordinates.foldersY;
final int height = coordinates.foldersHeight;
- final int ascent = coordinates.foldersAscent;
int textBottomPadding = coordinates.foldersTextBottomPadding;
sFoldersPaint.setTextSize(coordinates.foldersFontSize);
@@ -403,13 +429,6 @@
}
}
- /**
- * Helpers function to align an element in the center of a space.
- */
- private static int getPadding(int space, int length) {
- return (space - length) / 2;
- }
-
public ConversationItemView(Context context, String account) {
super(context);
Utils.traceBeginSection("CIVC constructor");
@@ -425,8 +444,10 @@
if (STAR_OFF == null) {
// Initialize static bitmaps.
- STAR_OFF = BitmapFactory.decodeResource(res, R.drawable.ic_star_off);
- STAR_ON = BitmapFactory.decodeResource(res, R.drawable.ic_star_on);
+ STAR_OFF = BitmapFactory.decodeResource(res, R.drawable.ic_btn_star_off);
+ STAR_ON = BitmapFactory.decodeResource(res, R.drawable.ic_btn_star_on);
+ PEEK = BitmapFactory.decodeResource(res, R.drawable.ic_peak_eye);
+ CHECK = BitmapFactory.decodeResource(res, R.drawable.ic_avatar_check);
ATTACHMENT = BitmapFactory.decodeResource(res, R.drawable.ic_attachment_holo_light);
ONLY_TO_ME = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_double);
TO_ME_AND_OTHERS = BitmapFactory.decodeResource(res, R.drawable.ic_email_caret_single);
@@ -451,8 +472,8 @@
PROGRESS_BAR = res.getDrawable(drawable.progress_holo);
// Initialize colors.
- sActivatedTextColor = res.getColor(R.color.senders_text_color_read);
- sActivatedTextSpan = CharacterStyle.wrap(new ForegroundColorSpan(sActivatedTextColor));
+ sActivatedTextSpan = CharacterStyle.wrap(new ForegroundColorSpan(
+ res.getColor(R.color.senders_text_color_read)));
sSendersTextColorRead = res.getColor(R.color.senders_text_color_read);
sSendersTextColorUnread = res.getColor(R.color.senders_text_color_unread);
sSubjectTextUnreadSpan = new TextAppearanceSpan(mContext,
@@ -464,23 +485,23 @@
sSnippetTextReadSpan =
new ForegroundColorSpan(res.getColor(R.color.snippet_text_color_read));
sDateTextColor = res.getColor(R.color.date_text_color);
+ sAttachmentPreviewsBackgroundColor = res.getColor(color.ap_background_color);
sOverflowBadgeColor = res.getColor(color.ap_overflow_badge_color);
sOverflowTextColor = res.getColor(color.ap_overflow_text_color);
sStarTouchSlop = res.getDimensionPixelSize(R.dimen.star_touch_slop);
sSenderImageTouchSlop = res.getDimensionPixelSize(R.dimen.sender_image_touch_slop);
- sStandardScaledDimen = res.getDimensionPixelSize(R.dimen.standard_scaled_dimen);
sShrinkAnimationDuration = res.getInteger(R.integer.shrink_animation_duration);
sSlideAnimationDuration = res.getInteger(R.integer.slide_animation_duration);
// Initialize static color.
sSendersSplitToken = res.getString(R.string.senders_split_token);
sElidedPaddingToken = res.getString(R.string.elided_padding_token);
sOverflowCountFormat = res.getString(string.ap_overflow_format);
- sAnimatingBackgroundColor = res.getColor(R.color.animating_item_background_color);
sScrollSlop = res.getInteger(R.integer.swipeScrollSlop);
sFoldersLeftPadding = res.getDimensionPixelOffset(R.dimen.folders_left_padding);
sContactPhotoManager = ContactPhotoManager.createContactPhotoManager(context);
sAttachmentPreviewsManager = new AttachmentPreviewsManager(context);
sProgressAnimationDuration = res.getInteger(integer.ap_progress_animation_duration);
+ sFadeAnimationDuration = res.getInteger(integer.ap_fade_animation_duration);
final int placeholderAnimationDuration = res
.getInteger(integer.ap_placeholder_animation_duration);
sPlaceholderAnimationDurationRatio = sProgressAnimationDuration
@@ -488,8 +509,34 @@
sProgressAnimationDelay = res.getInteger(integer.ap_progress_animation_delay);
sPulseAnimationInterpolator = new AccelerateDecelerateInterpolator();
sOverflowCountMax = res.getInteger(integer.ap_overflow_max_count);
+ sCabAnimationDuration =
+ res.getInteger(R.integer.conv_item_view_cab_anim_duration);
}
+ mPhotoFlipAnimator = new CabAnimator("photoFlipFraction", 0, 2,
+ sCabAnimationDuration) {
+ @Override
+ public void invalidateArea() {
+ final int left = mCoordinates.contactImagesX;
+ final int right = left + mContactImagesHolder.getWidth();
+ final int top = mCoordinates.contactImagesY;
+ final int bottom = top + mContactImagesHolder.getHeight();
+ invalidate(left, top, right, bottom);
+ }
+ };
+
+ mPeekIconFlipAnimator = new CabAnimator("peekIconFlipFraction", 0, 2,
+ sCabAnimationDuration) {
+ @Override
+ public void invalidateArea() {
+ final int left = mCoordinates.starX;
+ final int right = left + mCoordinates.starWidth;
+ final int top = mCoordinates.starY;
+ final int bottom = top + mCoordinates.starHeight;
+ invalidate(left, top, right, bottom);
+ }
+ };
+
mSendersTextView = new TextView(mContext);
mSendersTextView.setIncludeFontPadding(false);
@@ -526,29 +573,67 @@
});
mProgressAnimator = createProgressAnimator();
- mSetShowProgressBarRunnable = new Runnable() {
+ mFadeAnimator0 = createFadeAnimator(0);
+ mFadeAnimator1 = createFadeAnimator(1);
+ mCancelProgressAnimatorRunnable = new Runnable() {
@Override
public void run() {
- LogUtils.v(LOG_TAG, "progress bar: >>> set to true");
- // It's OK to set this field to true when the status is no longer LOADING.
+ if (mProgressAnimator.isStarted() && areAllImagesLoaded()) {
+ LogUtils.v(LOG_TAG, "progress animator: << stopped");
+ mProgressAnimator.cancel();
+ }
+ }
+ };
+ mSetShowProgressBarRunnable0 = new Runnable() {
+ @Override
+ public void run() {
+ if (mImageLoadStatuses.length <= 0
+ || mImageLoadStatuses[0] != PhotoManager.STATUS_LOADING) {
+ return;
+ }
+ LogUtils.v(LOG_TAG, "progress bar 0: >>> set to true");
mShowProgressBar = true;
+ if (mFadeAnimator0.isStarted()) {
+ mFadeAnimator0.cancel();
+ }
+ mFadeAnimator0.start();
+ }
+ };
+ mSetShowProgressBarRunnable1 = new Runnable() {
+ @Override
+ public void run() {
+ if (mImageLoadStatuses.length <= 1
+ || mImageLoadStatuses[1] != PhotoManager.STATUS_LOADING) {
+ return;
+ }
+ LogUtils.v(LOG_TAG, "progress bar 1: >>> set to true");
+ mShowProgressBar = true;
+ if (mFadeAnimator1.isStarted()) {
+ mFadeAnimator1.cancel();
+ }
+ mFadeAnimator1.start();
}
};
Utils.traceEndSection();
}
public void bind(Conversation conversation, ControllableActivity activity,
+ final ConversationListListener conversationListListener,
ConversationSelectionSet set, Folder folder, int checkboxOrSenderImage,
- boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
+ boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter,
+ final int adapterPosition) {
Utils.traceBeginSection("CIVC.bind");
- bind(ConversationItemViewModel.forConversation(mAccount, conversation), activity, set,
- folder, checkboxOrSenderImage, swipeEnabled, priorityArrowEnabled, adapter);
+ bind(ConversationItemViewModel.forConversation(mAccount, conversation), activity,
+ conversationListListener, set, folder, checkboxOrSenderImage, swipeEnabled,
+ priorityArrowEnabled, adapter, adapterPosition);
Utils.traceEndSection();
}
private void bind(ConversationItemViewModel header, ControllableActivity activity,
+ final ConversationListListener conversationListListener,
ConversationSelectionSet set, Folder folder, int checkboxOrSenderImage,
- boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter) {
+ boolean swipeEnabled, boolean priorityArrowEnabled, AnimatedAdapter adapter,
+ final int adapterPosition) {
boolean attachmentPreviewsChanged = false;
if (mHeader != null) {
// If this was previously bound to a different conversation, remove any contact photo
@@ -593,14 +678,22 @@
mCoordinates = null;
mHeader = header;
mActivity = activity;
+ mConversationListListener = conversationListListener;
mSelectedConversationSet = set;
mDisplayedFolder = folder;
mStarEnabled = folder != null && !folder.isTrash();
mSwipeEnabled = swipeEnabled;
+
+ if (mAdapter != null) {
+ mAdapter.unregisterConversationSetObserver(mConversationSetObserver);
+ }
mAdapter = adapter;
+ mAdapter.registerConversationSetObserver(mConversationSetObserver);
+
+ mAdapterPosition = adapterPosition;
final int attachmentPreviewsSize = mHeader.conversation.getAttachmentPreviewUris().size();
- if (attachmentPreviewsChanged || mImagesLoaded.length != attachmentPreviewsSize) {
- mImagesLoaded = new int[attachmentPreviewsSize];
+ if (attachmentPreviewsChanged || mImageLoadStatuses.length != attachmentPreviewsSize) {
+ mImageLoadStatuses = new int[attachmentPreviewsSize];
}
if (checkboxOrSenderImage == ConversationListIcon.SENDER_IMAGE) {
@@ -623,8 +716,8 @@
ignoreFolderType = -1;
}
- mHeader.folderDisplayer.loadConversationFolders(mHeader.conversation, mDisplayedFolder.uri,
- ignoreFolderType);
+ mHeader.folderDisplayer.loadConversationFolders(mHeader.conversation,
+ mDisplayedFolder.folderUri, ignoreFolderType);
mHeader.dateText = DateUtils.getRelativeTimeSpanString(mContext,
mHeader.conversation.dateMs);
@@ -722,8 +815,13 @@
super.onLayout(changed, left, top, right, bottom);
+ Utils.traceBeginSection("text and bitmaps");
calculateTextsAndBitmaps();
+ Utils.traceEndSection();
+
+ Utils.traceBeginSection("coordinates");
calculateCoordinates();
+ Utils.traceEndSection();
// Subject.
createSubject(mHeader.unread);
@@ -937,7 +1035,7 @@
uri);
int bestAvailableRendition = -1;
// BEST first, else use less preferred renditions
- for (int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
+ for (final int rendition : AttachmentRendition.PREFERRED_RENDITIONS) {
if (Attachment.getPreviewState(previewStates, i, rendition)) {
bestAvailableRendition = rendition;
break;
@@ -968,8 +1066,6 @@
Utils.traceEndSection();
Utils.traceBeginSection("start animator");
- // We want to show default progress image
- setImageLoaded(i, PhotoManager.STATUS_NOT_LOADED);
if (!mProgressAnimator.isStarted()) {
LogUtils.v(LOG_TAG, "progress animator: >> started");
// Reduce progress bar stutter caused by reset()/bind() being called multiple
@@ -983,6 +1079,7 @@
LogUtils.v(LOG_TAG, "progress animator: correction for dt %d, fraction %f",
dt, passedFraction);
}
+ removeCallbacks(mCancelProgressAnimatorRunnable);
mProgressAnimator.start();
// Wow.. this must be called after start().
mProgressAnimator.setCurrentPlayTime((long) (sProgressAnimationDuration * (
@@ -1013,12 +1110,12 @@
"loadAttachmentPreviews: <= onImageDrawn callback [%b] on index %d for %s", success,
index, key);
// We want to hide the spinning progress bar when we draw something.
- setImageLoaded(index,
+ onImageLoadStatusChanged(index,
success ? PhotoManager.STATUS_LOADED : PhotoManager.STATUS_NOT_LOADED);
if (mProgressAnimator.isStarted() && areAllImagesLoaded()) {
- LogUtils.v(LOG_TAG, "progress animator: << stopped");
- mProgressAnimator.cancel();
+ removeCallbacks(mCancelProgressAnimatorRunnable);
+ postDelayed(mCancelProgressAnimatorRunnable, sFadeAnimationDuration);
}
Utils.traceEndSection();
}
@@ -1034,12 +1131,12 @@
LogUtils.v(LOG_TAG,
"loadAttachmentPreviews: <= onImageLoadStarted callback on index %d for %s", index,
key);
- setImageLoaded(index, PhotoManager.STATUS_LOADING);
+ onImageLoadStatusChanged(index, PhotoManager.STATUS_LOADING);
}
private boolean areAllImagesLoaded() {
- for (int i = 0; i < mImagesLoaded.length; i++) {
- if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
+ for (int i = 0; i < mImageLoadStatuses.length; i++) {
+ if (mImageLoadStatuses[i] != PhotoManager.STATUS_LOADED) {
return false;
}
}
@@ -1047,44 +1144,60 @@
}
/**
- * Update the #mImagesLoaded state array with special logic.
+ * Update the #mImageLoadStatuses state array with special logic.
* @param index Which attachment preview's state to update.
* @param status What the new state is.
*/
- private void setImageLoaded(final int index, final int status) {
- if (index < 0 || index >= mImagesLoaded.length) {
+ private void onImageLoadStatusChanged(final int index, final int status) {
+ if (index < 0 || index >= mImageLoadStatuses.length) {
return;
}
- final int prevStatus = mImagesLoaded[index];
+ final int prevStatus = mImageLoadStatuses[index];
+ if (prevStatus == status) {
+ return;
+ }
+
+ boolean changed = false;
switch (status) {
case PhotoManager.STATUS_NOT_LOADED:
+ LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
+ mShowProgressBar = false;
// Cannot transition directly from LOADING to NOT_LOADED.
if (prevStatus != PhotoManager.STATUS_LOADING) {
- mImagesLoaded[index] = status;
+ mImageLoadStatuses[index] = status;
+ changed = true;
}
break;
case PhotoManager.STATUS_LOADING:
// All other statuses must be set to not loading.
- for (int i = 0; i < mImagesLoaded.length; i++) {
- if (i != index && mImagesLoaded[i] == PhotoManager.STATUS_LOADING) {
- mImagesLoaded[i] = PhotoManager.STATUS_NOT_LOADED;
+ for (int i = 0; i < mImageLoadStatuses.length; i++) {
+ if (i != index && mImageLoadStatuses[i] == PhotoManager.STATUS_LOADING) {
+ mImageLoadStatuses[i] = PhotoManager.STATUS_NOT_LOADED;
}
}
- mImagesLoaded[index] = status;
+ mImageLoadStatuses[index] = status;
- if (prevStatus != PhotoManager.STATUS_LOADING) {
- // Progress bar should only be shown after a delay
- LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
- mShowProgressBar = false;
- LogUtils.v(LOG_TAG, "progress bar: === start delay");
- removeCallbacks(mSetShowProgressBarRunnable);
- postDelayed(mSetShowProgressBarRunnable, sProgressAnimationDelay);
- }
+ // Progress bar should only be shown after a delay
+ LogUtils.v(LOG_TAG, "progress bar: <<< set to false");
+ mShowProgressBar = false;
+ LogUtils.v(LOG_TAG, "progress bar: === start delay");
+ final Runnable setShowProgressBarRunnable = index == 0
+ ? mSetShowProgressBarRunnable0 : mSetShowProgressBarRunnable1;
+ removeCallbacks(setShowProgressBarRunnable);
+ postDelayed(setShowProgressBarRunnable, sProgressAnimationDelay);
+ changed = true;
break;
case PhotoManager.STATUS_LOADED:
- mImagesLoaded[index] = status;
+ mImageLoadStatuses[index] = status;
+ changed = true;
break;
}
+ if (changed) {
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ if (!fadeAnimator.isStarted()) {
+ fadeAnimator.start();
+ }
+ }
}
private static int makeExactSpecForSize(int size) {
@@ -1194,8 +1307,6 @@
}
// Second pass to layout each fragment.
- int sendersY = mCoordinates.sendersY - mCoordinates.sendersAscent;
-
sPaint.setTextSize(mCoordinates.sendersFontSize);
sPaint.setTypeface(Typeface.DEFAULT);
@@ -1219,9 +1330,6 @@
totalWidth += senderFragment.width;
}
- if (!ConversationItemViewCoordinates.displaySendersInline(mCoordinates.getMode())) {
- sendersY += totalWidth <= mSendersWidth ? mCoordinates.sendersLineHeight / 2 : 0;
- }
if (mSendersWidth < 0) {
mSendersWidth = 0;
}
@@ -1440,7 +1548,7 @@
// Contact photo
if (mGadgetMode == ConversationItemViewCoordinates.GADGET_CONTACT_PHOTO) {
canvas.save();
- drawContactImages(canvas);
+ drawContactImageArea(canvas);
canvas.restore();
}
@@ -1515,9 +1623,12 @@
canvas.drawBitmap(mHeader.paperclip, mPaperclipX, mCoordinates.paperclipY, sPaint);
}
- if (mStarEnabled) {
- // Star.
- canvas.drawBitmap(getStarBitmap(), mCoordinates.starX, mCoordinates.starY, sPaint);
+ if (mConversationListListener.isInSelectionMode()) {
+ drawStarPeekIcon(canvas, mConversationListListener.isEnteringSelectionMode(),
+ false /* reverse */, PEEK);
+ } else if (mStarEnabled) {
+ drawStarPeekIcon(canvas, mConversationListListener.isExitingSelectionMode(),
+ true /* reverse */, getStarBitmap());
}
// Attachment previews
@@ -1539,39 +1650,30 @@
drawText(canvas, mHeader.overflowText, mOverflowX, mOverflowY, sPaint);
}
- // Progress bar
- if (mProgressAnimator.isRunning()) {
- // Fade from 55 -> 255 -> 55. Each cycle lasts for #sProgressAnimationDuration secs.
- final int maxAlpha = 255, minAlpha = 55;
- final int range = maxAlpha - minAlpha;
- // We want the placeholder to pulse at a different rate from the progressbar to
- // spin.
- final float placeholderAnimFraction = mAnimatedProgressFraction
- * sPlaceholderAnimationDurationRatio;
- // During the time that placeholderAnimFraction takes to go from 0 to 1, we
- // want to go all the way to #maxAlpha and back down to #minAlpha. So from 0 to 0.5,
- // we increase #modifiedProgress from 0 to 1, while from 0.5 to 1 we decrease
- // accordingly from 1 to 0. Math.
- final float modifiedProgress = -2 * Math.abs(placeholderAnimFraction - 0.5f) + 1;
- // Make it feel like a heart beat.
- final float interpolatedProgress = sPulseAnimationInterpolator
- .getInterpolation(modifiedProgress);
- // More math.
- final int alpha = (int) (interpolatedProgress * range + minAlpha);
- sPaint.setAlpha(alpha);
+ // Placeholders and progress bars
- final int count = mImagesLoaded.length;
- for (int i = 0; i < count; i++) {
- if (mShowProgressBar && mImagesLoaded[i] == PhotoManager.STATUS_LOADING) {
- // status is LOADING and enough time has passed
- canvas.save();
- drawProgressBar(canvas, i, count);
- canvas.restore();
- } else if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
- // status is either NOT_LOADED or LOADING
- drawPlaceholder(canvas, i, count);
- }
- }
+ // Fade from 55 -> 255 -> 55. Each cycle lasts for #sProgressAnimationDuration secs.
+ final int maxAlpha = 255, minAlpha = 55;
+ final int range = maxAlpha - minAlpha;
+ // We want the placeholder to pulse at a different rate from the progressbar to
+ // spin.
+ final float placeholderAnimFraction = mAnimatedProgressFraction
+ * sPlaceholderAnimationDurationRatio;
+ // During the time that placeholderAnimFraction takes to go from 0 to 1, we
+ // want to go all the way to #maxAlpha and back down to #minAlpha. So from 0 to 0.5,
+ // we increase #modifiedProgress from 0 to 1, while from 0.5 to 1 we decrease
+ // accordingly from 1 to 0. Math.
+ final float modifiedProgress = -2 * Math.abs(placeholderAnimFraction - 0.5f) + 1;
+ // Make it feel like a heart beat.
+ final float interpolatedProgress = sPulseAnimationInterpolator
+ .getInterpolation(modifiedProgress);
+ // More math.
+ final int pulseAlpha = (int) (interpolatedProgress * range + minAlpha);
+
+ final int count = mImageLoadStatuses.length;
+ for (int i = 0; i < count; i++) {
+ drawPlaceholder(canvas, i, count, pulseAlpha);
+ drawProgressBar(canvas, i, count);
}
}
@@ -1592,9 +1694,146 @@
Utils.traceEndSection();
}
- private void drawContactImages(Canvas canvas) {
+ private void drawStarPeekIcon(final Canvas canvas, final boolean animate, final boolean reverse,
+ final Bitmap staticIcon) {
+ if (animate) {
+ // Animate the peek icon
+ if (!mPeekIconFlipAnimator.isStarted()) {
+ mPeekIconFlipAnimator.startAnimation(reverse);
+ }
+
+ canvas.save();
+
+ final float value = mPeekIconFlipAnimator.getValue();
+ final float scale;
+ final Bitmap bitmap;
+
+ if (value > 1) {
+ // Flip in the peek icon
+ scale = value - 1f;
+ bitmap = PEEK;
+ } else {
+ // Flip out the star icon
+ scale = 1f - value;
+ bitmap = getStarBitmap();
+ }
+
+ final float yOffset = mCoordinates.starHeight * (1f - scale) / 2f;
+
+ mPeekIconFlipMatrix.reset();
+ mPeekIconFlipMatrix.postScale(1, scale);
+
+ canvas.translate(mCoordinates.starX, mCoordinates.starY + yOffset);
+
+ canvas.drawBitmap(bitmap, mPeekIconFlipMatrix, sPaint);
+
+ canvas.restore();
+ } else {
+ mPeekIconFlipAnimator.stopAnimation();
+
+ // Star/Peek icon
+ canvas.drawBitmap(staticIcon, mCoordinates.starX, mCoordinates.starY, sPaint);
+ }
+ }
+
+ /**
+ * Draws the contact images or check, in the correct animated state.
+ */
+ private void drawContactImageArea(final Canvas canvas) {
+ if (isSelected()) {
+ mLastSelectedId = mHeader.conversation.id;
+
+ // Since this is selected, we draw the checkbox if the animation is not running, or if
+ // it's running, and is past the half-way point
+ if (mPhotoFlipAnimator.getValue() > 1 || !mPhotoFlipAnimator.isStarted()) {
+ // Flash in the check
+ drawCheckbox(canvas);
+ } else {
+ // Flip out the contact photo
+ drawContactImages(canvas);
+ }
+ } else {
+ if ((mConversationListListener.isExitingSelectionMode()
+ && mLastSelectedId == mHeader.conversation.id)
+ || mPhotoFlipAnimator.isStarted()) {
+ // Animate back to the photo
+ if (!mPhotoFlipAnimator.isStarted()) {
+ mPhotoFlipAnimator.startAnimation(true /* reverse */);
+ }
+
+ if (mPhotoFlipAnimator.getValue() > 1) {
+ // Flash out the check
+ drawCheckbox(canvas);
+ } else {
+ // Flip in the contact photo
+ drawContactImages(canvas);
+ }
+ } else {
+ mLastSelectedId = -1; // We don't care anymore
+ mPhotoFlipAnimator.stopAnimation(); // It's not running, but we want to reset state
+
+ // Contact photos
+ drawContactImages(canvas);
+ }
+ }
+ }
+
+ private void drawContactImages(final Canvas canvas) {
+ // mPhotoFlipFraction goes from 0 to 1
+ final float value = mPhotoFlipAnimator.getValue();
+
+ final float scale = 1f - value;
+ final float xOffset = mContactImagesHolder.getWidth() * value / 2;
+
+ mPhotoFlipMatrix.reset();
+ mPhotoFlipMatrix.postScale(scale, 1);
+
+ canvas.translate(mCoordinates.contactImagesX + xOffset, mCoordinates.contactImagesY);
+
+ mContactImagesHolder.draw(canvas, mPhotoFlipMatrix);
+ }
+
+ private void drawCheckbox(final Canvas canvas) {
+ // mPhotoFlipFraction goes from 1 to 2
+
+ // Draw the background
+ canvas.save();
canvas.translate(mCoordinates.contactImagesX, mCoordinates.contactImagesY);
- mContactImagesHolder.draw(canvas);
+ canvas.drawRect(0, 0, mCoordinates.contactImagesWidth, mCoordinates.contactImagesHeight,
+ sCheckBackgroundPaint);
+ canvas.restore();
+
+ final int x = mCoordinates.contactImagesX
+ + (mCoordinates.contactImagesWidth - CHECK.getWidth()) / 2;
+ final int y = mCoordinates.contactImagesY
+ + (mCoordinates.contactImagesHeight - CHECK.getHeight()) / 2;
+
+ final float value = mPhotoFlipAnimator.getValue();
+ final float scale;
+
+ if (!mPhotoFlipAnimator.isStarted()) {
+ // We're not animating
+ scale = 1;
+ } else if (value < 1.9) {
+ // 1.0 to 1.9 will scale 0 to 1
+ scale = (value - 1f) / 0.9f;
+ } else if (value < 1.95) {
+ // 1.9 to 1.95 will scale 1 to 19/18
+ scale = (value - 1f) / 0.9f;
+ } else {
+ // 1.95 to 2.0 will scale 19/18 to 1
+ scale = (0.95f - (value - 1.95f)) / 0.9f;
+ }
+
+ final float xOffset = CHECK.getWidth() * (1f - scale) / 2f;
+ final float yOffset = CHECK.getHeight() * (1f - scale) / 2f;
+
+ mCheckMatrix.reset();
+ mCheckMatrix.postScale(scale, scale);
+
+ canvas.translate(x + xOffset, y + yOffset);
+
+ canvas.drawBitmap(CHECK, mCheckMatrix, sPaint);
}
private void drawAttachmentPreviews(Canvas canvas) {
@@ -1614,16 +1853,47 @@
/**
* Draws the specified placeholder on the canvas.
+ *
* @param canvas The canvas to draw on.
- * @param index If drawing multiple progress bars, this determines which one we are drawing.
- * @param total Whether we are drawing multiple progress bars.
+ * @param index If drawing multiple placeholders, this determines which one we are drawing.
+ * @param total Whether we are drawing multiple placeholders.
+ * @param pulseAlpha The alpha to draw this at.
*/
- private void drawPlaceholder(Canvas canvas, int index, int total) {
- int placeholderX = getPlaceholderX(index, total);
+ private void drawPlaceholder(final Canvas canvas, final int index, final int total,
+ final int pulseAlpha) {
+ final int placeholderX = getAttachmentPreviewXCenter(index, total)
+ - mCoordinates.placeholderWidth / 2;
if (placeholderX == -1) {
return;
}
+ // Set alpha for crossfading effect.
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ final float animatedFadeFraction = index == 0 ? mAnimatedFadeFraction0
+ : mAnimatedFadeFraction1;
+ final boolean notLoaded = mImageLoadStatuses[index] == PhotoManager.STATUS_NOT_LOADED;
+ final boolean loading = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADING;
+ final boolean loaded = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADED;
+ final float fadeAlphaFraction;
+ if (notLoaded) {
+ fadeAlphaFraction = 1.0f;
+ } else if (loading && !mShowProgressBar) {
+ fadeAlphaFraction = 1.0f;
+ } else if (fadeAnimator.isStarted() && (loading && mShowProgressBar
+ || loaded && !mShowProgressBar)) {
+ // Fade to progress bar or fade to image from placeholder
+ fadeAlphaFraction = 1.0f - animatedFadeFraction;
+ } else {
+ fadeAlphaFraction = 0.0f;
+ }
+
+ if (fadeAlphaFraction == 0.0f) {
+ return;
+ }
+ // Draw background
+ drawAttachmentPreviewBackground(canvas, index, total, (int) (255 * fadeAlphaFraction));
+
+ sPaint.setAlpha((int) (pulseAlpha * fadeAlphaFraction));
canvas.drawBitmap(PLACEHOLDER, placeholderX, mCoordinates.placeholderY, sPaint);
}
@@ -1633,62 +1903,114 @@
* @param index If drawing multiple progress bars, this determines which one we are drawing.
* @param total Whether we are drawing multiple progress bars.
*/
- private void drawProgressBar(Canvas canvas, int index, int total) {
- int progressBarX = getProgressBarX(index, total);
+ private void drawProgressBar(final Canvas canvas, final int index, final int total) {
+ final int progressBarX = getAttachmentPreviewXCenter(index, total)
+ - mCoordinates.progressBarWidth / 2;
if (progressBarX == -1) {
return;
}
+ // Set alpha for crossfading effect.
+ final ObjectAnimator fadeAnimator = index == 0 ? mFadeAnimator0 : mFadeAnimator1;
+ final float animatedFadeFraction = index == 0 ? mAnimatedFadeFraction0
+ : mAnimatedFadeFraction1;
+ final boolean loading = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADING;
+ final boolean loaded = mImageLoadStatuses[index] == PhotoManager.STATUS_LOADED;
+ final int fadeAlpha;
+ if (loading && mShowProgressBar) {
+ fadeAlpha = (int) (255 * animatedFadeFraction);
+ } else if (fadeAnimator.isStarted() && (loaded && mShowProgressBar)) {
+ // Fade to image from progress bar
+ fadeAlpha = (int) (255 * (1.0f - animatedFadeFraction));
+ } else {
+ fadeAlpha = 0;
+ }
+
+ if (fadeAlpha == 0) {
+ return;
+ }
+
+ // Draw background
+ drawAttachmentPreviewBackground(canvas, index, total, fadeAlpha);
+
// Set the level from 0 to 10000 to animate the Drawable.
PROGRESS_BAR.setLevel((int) (mAnimatedProgressFraction * 10000));
// canvas.translate() for Bitmaps, setBounds() for Drawables.
PROGRESS_BAR.setBounds(progressBarX, mCoordinates.progressBarY,
progressBarX + mCoordinates.progressBarWidth,
mCoordinates.progressBarY + mCoordinates.progressBarHeight);
+ PROGRESS_BAR.setAlpha(fadeAlpha);
PROGRESS_BAR.draw(canvas);
}
-
/**
- * @see com.android.mail.browse.ConversationItemView#drawProgressBar
+ * Draws the specified attachment previews background on the canvas.
+ * @param canvas The canvas to draw on.
+ * @param index If drawing for multiple attachment previews, this determines for which one's
+ * background we are drawing.
+ * @param total Whether we are drawing for multiple attachment previews.
+ * @param fadeAlpha The alpha to draw this at.
*/
- private void invalidatePlaceholderAndProgressBar(int index, int total) {
- int progressBarX = getProgressBarX(index, total);
- if (progressBarX == -1) {
+ private void drawAttachmentPreviewBackground(final Canvas canvas, final int index,
+ final int total, final int fadeAlpha) {
+ if (total == 0) {
return;
}
-
- invalidate(progressBarX, mCoordinates.progressBarY,
- progressBarX + mCoordinates.progressBarWidth,
- mCoordinates.progressBarY + mCoordinates.progressBarHeight);
-
- int placeholderX = getPlaceholderX(index, total);
- if (placeholderX == -1) {
- return;
- }
-
- invalidate(placeholderX, mCoordinates.placeholderY,
- placeholderX + mCoordinates.placeholderWidth,
- mCoordinates.placeholderY + mCoordinates.placeholderHeight);
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ final int sectionX = getAttachmentPreviewX(index, total);
+ sPaint.setColor(sAttachmentPreviewsBackgroundColor);
+ sPaint.setAlpha(fadeAlpha);
+ canvas.drawRect(sectionX, mCoordinates.attachmentPreviewsY, sectionX + sectionWidth,
+ mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight, sPaint);
}
- private int getPlaceholderX(int index, int total) {
- if (mCoordinates == null) {
- return -1;
+ private void invalidateAttachmentPreviews() {
+ final int total = mImageLoadStatuses.length;
+ for (int index = 0; index < total; index++) {
+ invalidateAttachmentPreview(index, total);
}
- int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
- int sectionOffset = index * sectionWidth;
- return mCoordinates.attachmentPreviewsX + sectionOffset + sectionWidth / 2
- - mCoordinates.placeholderWidth / 2;
}
- private int getProgressBarX(int index, int total) {
- if (mCoordinates == null) {
+ private void invalidatePlaceholdersAndProgressBars() {
+ final int total = mImageLoadStatuses.length;
+ for (int index = 0; index < total; index++) {
+ invalidatePlaceholderAndProgressBar(index, total);
+ }
+ }
+
+ private void invalidateAttachmentPreview(final int index, final int total) {
+ invalidate(getAttachmentPreviewX(index, total), mCoordinates.attachmentPreviewsY,
+ getAttachmentPreviewX(index + 1, total),
+ mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight);
+ }
+
+ private void invalidatePlaceholderAndProgressBar(final int index, final int total) {
+ final int width = Math.max(mCoordinates.placeholderWidth, mCoordinates.progressBarWidth);
+ final int height = Math.max(mCoordinates.placeholderHeight, mCoordinates.progressBarHeight);
+ final int x = getAttachmentPreviewXCenter(index, total) - width / 2;
+ final int xEnd = getAttachmentPreviewXCenter(index, total) + width / 2;
+ final int yCenter = mCoordinates.attachmentPreviewsY
+ + mCoordinates.attachmentPreviewsHeight / 2;
+ final int y = yCenter - height / 2;
+ final int yEnd = yCenter + height / 2;
+
+ invalidate(x, y, xEnd, yEnd);
+ }
+
+ private int getAttachmentPreviewX(final int index, final int total) {
+ if (mCoordinates == null || total == 0) {
return -1;
}
- int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
- int sectionOffset = index * sectionWidth;
- return mCoordinates.attachmentPreviewsX + sectionOffset + sectionWidth / 2
- - mCoordinates.progressBarWidth / 2;
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ final int sectionOffset = index * sectionWidth;
+ return mCoordinates.attachmentPreviewsX + sectionOffset;
+ }
+
+ private int getAttachmentPreviewXCenter(final int index, final int total) {
+ if (total == 0) {
+ return -1;
+ }
+ final int sectionWidth = mCoordinates.attachmentPreviewsWidth / total;
+ return getAttachmentPreviewX(index, total) + sectionWidth / 2;
}
private Bitmap getStarBitmap() {
@@ -1747,6 +2069,11 @@
if (mSelectedConversationSet.isEmpty()) {
listView.commitDestructiveActions(true);
}
+
+ final boolean reverse = !mSelected;
+ mPhotoFlipAnimator.startAnimation(reverse);
+ mPhotoFlipAnimator.invalidateArea();
+
// We update the background after the checked state has changed
// now that we have a selected background asset. Setting the background
// usually waits for a layout pass, but we don't need a full layout,
@@ -1771,16 +2098,11 @@
}
}
- public void viewAttachmentPreview(final int index) {
- final String attachmentUri = mHeader.conversation.getAttachmentPreviewUris().get(index);
- final Uri imageListUri = mHeader.conversation.attachmentPreviewsListUri;
- LogUtils.d(LOG_TAG,
- "ConversationItemView: tapped on attachment preview %d, "
- + "opening photoviewer for image list uri %s",
- index, imageListUri);
- MailPhotoViewActivity
- .startMailPhotoViewActivity(mActivity.getActivityContext(), imageListUri,
- attachmentUri);
+ /**
+ * Peek into the conversation.
+ */
+ private void peek() {
+ mConversationListListener.viewConversation(mAdapterPosition);
}
private boolean isTouchInContactPhoto(float x, float y) {
@@ -1798,29 +2120,6 @@
&& (!isAttachmentPreviewsEnabled() || y < mCoordinates.attachmentPreviewsY);
}
- /**
- * If the touch is in the attachment previews, return the index of the attachment under that
- * point (for multiple previews). Return -1 if the touch is outside of the previews.
- *
- * @return The index corresponding to where the attachment appears on the screen. This index
- * may not be the same as the attachment's actual index in the message.
- */
- private int getAttachmentPreviewsIndexForTouch(float x, float y) {
- if (!isAttachmentPreviewsEnabled()) {
- return -1;
- }
- if (y > mCoordinates.attachmentPreviewsY
- && y < mCoordinates.attachmentPreviewsY + mCoordinates.attachmentPreviewsHeight
- && x > mCoordinates.attachmentPreviewsX
- && x < mCoordinates.attachmentPreviewsX + mCoordinates.attachmentPreviewsWidth) {
- int eachWidth = mCoordinates.attachmentPreviewsWidth / mHeader.conversation
- .getAttachmentPreviewUris().size();
- int offset = (int) (x - mCoordinates.attachmentPreviewsX);
- return offset / eachWidth;
- }
- return -1;
- }
-
@Override
public boolean canChildBeDismissed() {
return true;
@@ -1844,8 +2143,7 @@
mLastTouchY = y;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)
- || getAttachmentPreviewsIndexForTouch(x, y) > -1) {
+ if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)) {
mDownEvent = true;
handled = true;
}
@@ -1857,16 +2155,17 @@
case MotionEvent.ACTION_UP:
if (mDownEvent) {
- int index;
if (isTouchInContactPhoto(x, y)) {
// Touch on the check mark
toggleSelectedState();
} else if (isTouchInStar(x, y)) {
- // Touch on the star
- toggleStar();
- } else if ((index = getAttachmentPreviewsIndexForTouch(x, y)) > -1) {
- // Touch on an attachment preview
- viewAttachmentPreview(index);
+ // Touch on the star/peek
+ if (mConversationListListener.isInSelectionMode()) {
+ // Peek
+ peek();
+ } else {
+ toggleStar();
+ }
}
handled = true;
}
@@ -1897,8 +2196,7 @@
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)
- || getAttachmentPreviewsIndexForTouch(x, y) > -1) {
+ if (isTouchInContactPhoto(x, y) || isTouchInStar(x, y)) {
mDownEvent = true;
Utils.traceEndSection();
return true;
@@ -1906,7 +2204,6 @@
break;
case MotionEvent.ACTION_UP:
if (mDownEvent) {
- int index;
if (isTouchInContactPhoto(x, y)) {
// Touch on the check mark
Utils.traceEndSection();
@@ -1915,15 +2212,14 @@
Utils.traceEndSection();
return true;
} else if (isTouchInStar(x, y)) {
- // Touch on the star
+ // Touch on the star/peek
mDownEvent = false;
- toggleStar();
- Utils.traceEndSection();
- return true;
- } else if ((index = getAttachmentPreviewsIndexForTouch(x, y)) > -1) {
- // Touch on an attachment preview
- mDownEvent = false;
- viewAttachmentPreview(index);
+ if (mConversationListListener.isInSelectionMode()) {
+ // Peek
+ peek();
+ } else {
+ toggleStar();
+ }
Utils.traceEndSection();
return true;
}
@@ -1970,8 +2266,8 @@
setTranslationX(0f);
mAnimatedHeightFraction = 1.0f;
if (mProgressAnimator.isStarted()) {
- LogUtils.v(LOG_TAG, "progress animator: << stopped");
- mProgressAnimator.cancel();
+ removeCallbacks(mCancelProgressAnimatorRunnable);
+ postDelayed(mCancelProgressAnimatorRunnable, sFadeAnimationDuration);
}
Utils.traceEndSection();
}
@@ -2068,7 +2364,7 @@
private ObjectAnimator createProgressAnimator() {
final ObjectAnimator animator = ObjectAnimator
- .ofFloat(this, "animatedProgressFraction", 0f, 1.0f).setDuration(
+ .ofFloat(this, "animatedProgressFraction", 0.0f, 1.0f).setDuration(
sProgressAnimationDuration);
animator.setInterpolator(new LinearInterpolator());
animator.setRepeatCount(ObjectAnimator.INFINITE);
@@ -2086,10 +2382,27 @@
}
private void invalidateAll() {
- final int count = mHeader.conversation.getAttachmentPreviewUris().size();
- for (int i = 0; i < count; i++) {
- invalidatePlaceholderAndProgressBar(i, count);
- }
+ invalidatePlaceholdersAndProgressBars();
+ }
+ });
+ return animator;
+ }
+
+ private ObjectAnimator createFadeAnimator(final int index) {
+ final ObjectAnimator animator = ObjectAnimator
+ .ofFloat(this, "animatedFadeFraction" + index, 0.0f, 1.0f).setDuration(
+ sFadeAnimationDuration);
+ animator.setInterpolator(new DecelerateInterpolator());
+ animator.setRepeatCount(0);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(final Animator animation) {
+ invalidateAttachmentPreview(index, mImageLoadStatuses.length);
+ }
+
+ @Override
+ public void onAnimationCancel(final Animator animation) {
+ invalidateAttachmentPreview(index, mImageLoadStatuses.length);
}
});
return animator;
@@ -2102,12 +2415,19 @@
return;
}
mAnimatedProgressFraction = fraction;
- final int count = mImagesLoaded.length;
- for (int i = 0; i < count; i++) {
- if (mImagesLoaded[i] != PhotoManager.STATUS_LOADED) {
- invalidatePlaceholderAndProgressBar(i, count);
- }
- }
+ invalidatePlaceholdersAndProgressBars();
+ }
+
+ // Used by animator
+ public void setAnimatedFadeFraction0(final float fraction) {
+ mAnimatedFadeFraction0 = fraction;
+ invalidateAttachmentPreview(0, mImageLoadStatuses.length);
+ }
+
+ // Used by animator
+ public void setAnimatedFadeFraction1(final float fraction) {
+ mAnimatedFadeFraction1 = fraction;
+ invalidateAttachmentPreview(1, mImageLoadStatuses.length);
}
@Override
@@ -2187,11 +2507,12 @@
@Override
public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
- int width = mView.getWidth();
- int height = mView.getHeight();
+ final int width = mView.getWidth();
+ final int height = mView.getHeight();
+
+ sPaint.setTextSize(mCoordinates.subjectFontSize);
mDragDescX = mCoordinates.sendersX;
- mDragDescY = getPadding(height, (int) mCoordinates.subjectFontSize)
- - mCoordinates.subjectAscent;
+ mDragDescY = (height - (int) mCoordinates.subjectFontSize) / 2 ;
shadowSize.set(width, height);
shadowTouchPoint.set(mTouchX, mTouchY);
}
@@ -2201,7 +2522,7 @@
mBackground.setBounds(0, 0, mView.getWidth(), mView.getHeight());
mBackground.draw(canvas);
sPaint.setTextSize(mCoordinates.subjectFontSize);
- canvas.drawText(mDragDesc, mDragDescX, mDragDescY, sPaint);
+ canvas.drawText(mDragDesc, mDragDescX, mDragDescY - sPaint.ascent(), sPaint);
}
}
@@ -2209,4 +2530,111 @@
public float getMinAllowScrollDistance() {
return sScrollSlop;
}
+
+ private abstract class CabAnimator {
+ private ObjectAnimator mAnimator = null;
+
+ private final String mPropertyName;
+
+ private float mValue;
+
+ private final float mStartValue;
+ private final float mEndValue;
+
+ private final long mDuration;
+
+ public CabAnimator(final String propertyName, final float startValue, final float endValue,
+ final long duration) {
+ mPropertyName = propertyName;
+
+ mStartValue = startValue;
+ mEndValue = endValue;
+
+ mDuration = duration;
+ }
+
+ private ObjectAnimator createAnimator() {
+ final ObjectAnimator animator = ObjectAnimator.ofFloat(ConversationItemView.this,
+ mPropertyName, mStartValue, mEndValue);
+ animator.setDuration(mDuration);
+ animator.setInterpolator(new LinearInterpolator());
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(final Animator animation) {
+ invalidateArea();
+ }
+ });
+ return animator;
+ }
+
+ public abstract void invalidateArea();
+
+ public void setValue(final float fraction) {
+ mValue = fraction;
+ invalidateArea();
+ }
+
+ public float getValue() {
+ return mValue;
+ }
+
+ /**
+ * @param reverse <code>true</code> to animate in reverse
+ */
+ public void startAnimation(final boolean reverse) {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+
+ mAnimator = createAnimator();
+
+ if (reverse) {
+ mAnimator.reverse();
+ } else {
+ mAnimator.start();
+ }
+ }
+
+ public void stopAnimation() {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ mAnimator = null;
+ }
+
+ setValue(0);
+ }
+
+ public boolean isStarted() {
+ return mAnimator != null && mAnimator.isStarted();
+ }
+ }
+
+ public void setPhotoFlipFraction(final float fraction) {
+ mPhotoFlipAnimator.setValue(fraction);
+ }
+
+ public void setPeekIconFlipFraction(final float fraction) {
+ mPeekIconFlipAnimator.setValue(fraction);
+ }
+
+ private final ConversationSetObserver mConversationSetObserver = new ConversationSetObserver() {
+ @Override
+ public void onSetPopulated(final ConversationSelectionSet set) {
+ // Animate the peek icon in
+ // This will trigger a draw, which will start an animation
+ mPeekIconFlipAnimator.invalidateArea();
+ }
+
+ @Override
+ public void onSetEmpty() {
+ // Animate the peek icon out
+ // This will trigger a draw, which will start an animation
+ mPeekIconFlipAnimator.invalidateArea();
+ }
+
+ @Override
+ public void onSetChanged(final ConversationSelectionSet set) {
+ // Don't do anything
+ }
+ };
}
diff --git a/src/com/android/mail/browse/ConversationItemViewCoordinates.java b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
index 543f636..00322db 100644
--- a/src/com/android/mail/browse/ConversationItemViewCoordinates.java
+++ b/src/com/android/mail/browse/ConversationItemViewCoordinates.java
@@ -169,14 +169,11 @@
final int height;
- // Checkmark.
- final int checkmarkX;
- final int checkmarkY;
-
// Star.
final int starX;
final int starY;
final int starWidth;
+ final int starHeight;
// Senders.
final int sendersX;
@@ -186,7 +183,6 @@
final int sendersLineCount;
final int sendersLineHeight;
final float sendersFontSize;
- final int sendersAscent;
// Subject.
final int subjectX;
@@ -195,7 +191,6 @@
final int subjectHeight;
final int subjectLineCount;
final float subjectFontSize;
- final int subjectAscent;
// Folders.
final int foldersX;
@@ -204,7 +199,6 @@
final int foldersHeight;
final Typeface foldersTypeface;
final float foldersFontSize;
- final int foldersAscent;
final int foldersTextBottomPadding;
// Date.
@@ -212,7 +206,6 @@
final int dateY;
final int datePaddingLeft;
final float dateFontSize;
- final int dateAscent;
final int dateYBaseline;
// Paperclip.
@@ -317,24 +310,18 @@
: View.GONE);
View contactImagesView = view.findViewById(R.id.contact_image);
- View checkmark = view.findViewById(R.id.checkmark);
switch (config.getGadgetMode()) {
case GADGET_CONTACT_PHOTO:
contactImagesView.setVisibility(View.VISIBLE);
- checkmark.setVisibility(View.GONE);
- checkmark = null;
break;
case GADGET_CHECKBOX:
contactImagesView.setVisibility(View.GONE);
- checkmark.setVisibility(View.VISIBLE);
contactImagesView = null;
break;
default:
contactImagesView.setVisibility(View.GONE);
- checkmark.setVisibility(View.GONE);
contactImagesView = null;
- checkmark = null;
break;
}
@@ -355,12 +342,6 @@
// Utils.dumpViewTree((ViewGroup) view);
// Records coordinates.
- if (checkmark != null) {
- checkmarkX = getX(checkmark);
- checkmarkY = getY(checkmark);
- } else {
- checkmarkX = checkmarkY = 0;
- }
// Contact images view
if (contactImagesView != null) {
@@ -376,6 +357,7 @@
starX = getX(star);
starY = getY(star);
starWidth = star.getWidth();
+ starHeight = star.getHeight();
final TextView senders = (TextView) view.findViewById(R.id.senders);
final int sendersTopAdjust = getLatinTopAdjustment(senders);
@@ -386,7 +368,6 @@
sendersLineCount = getLineCount(senders);
sendersLineHeight = senders.getLineHeight();
sendersFontSize = senders.getTextSize();
- sendersAscent = (int) senders.getPaint().ascent();
final TextView subject = (TextView) view.findViewById(R.id.subject);
final int subjectTopAdjust = getLatinTopAdjustment(subject);
@@ -400,7 +381,6 @@
subjectHeight = subject.getHeight();
subjectLineCount = getLineCount(subject);
subjectFontSize = subject.getTextSize();
- subjectAscent = (int) subject.getPaint().ascent();
if (config.areFoldersVisible()) {
// vertically align folders min left edge with subject
@@ -416,7 +396,6 @@
foldersTextBottomPadding = res
.getDimensionPixelSize(R.dimen.folders_text_bottom_padding);
foldersFontSize = folders.getTextSize();
- foldersAscent = (int) folders.getPaint().ascent();
} else {
foldersX = 0;
foldersXEnd = 0;
@@ -425,7 +404,6 @@
foldersTypeface = null;
foldersTextBottomPadding = 0;
foldersFontSize = 0;
- foldersAscent = 0;
}
final View colorBlock = view.findViewById(R.id.color_block);
@@ -458,29 +436,21 @@
datePaddingLeft = date.getPaddingLeft();
dateFontSize = date.getTextSize();
dateYBaseline = dateY + getLatinTopAdjustment(date) + date.getBaseline();
- dateAscent = (int) date.getPaint().ascent();
final View paperclip = view.findViewById(R.id.paperclip);
paperclipY = getY(paperclip);
paperclipPaddingLeft = paperclip.getPaddingLeft();
if (attachmentPreviews != null) {
- attachmentPreviewsX = getAttachmentPreviewsX(attachmentPreviews,
- config.mAttachmentPreviewMode);
+ attachmentPreviewsX = subjectX;
attachmentPreviewsY = getY(attachmentPreviews) + sendersTopAdjust;
- final int attachmentPreviewsXEnd;
- if (isWide()) {
- attachmentPreviewsXEnd = subjectX + subjectWidth;
- } else {
- attachmentPreviewsXEnd = starX + starWidth;
- }
-
- attachmentPreviewsWidth = attachmentPreviewsXEnd - attachmentPreviewsX;
+ attachmentPreviewsWidth = subjectWidth;
attachmentPreviewsHeight = attachmentPreviews.getHeight();
// We only care about the right and bottom of the overflow count
final TextView overflow = (TextView) view.findViewById(id.ap_overflow);
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) overflow.getLayoutParams();
+ final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) overflow
+ .getLayoutParams();
overflowXEnd = attachmentPreviewsX + attachmentPreviewsWidth - params.rightMargin;
overflowYEnd = attachmentPreviewsY + attachmentPreviewsHeight - params.bottomMargin;
overflowDiameter = overflow.getWidth();
@@ -558,15 +528,9 @@
}
}
- private int getAttachmentPreviewsX(View attachmentPreviews, int attachmentPreviewMode) {
- if (isWide() || attachmentPreviewMode == ATTACHMENT_PREVIEW_READ) {
- return subjectX;
- }
- return getX(attachmentPreviews);
- }
-
- private int getAttachmentPreviewsHeight(Context context, int attachmentPreviewMode) {
- Resources res = context.getResources();
+ private int getAttachmentPreviewsHeight(final Context context,
+ final int attachmentPreviewMode) {
+ final Resources res = context.getResources();
switch (attachmentPreviewMode) {
case ATTACHMENT_PREVIEW_UNREAD:
return (int) (isWide() ? res.getDimension(dimen.attachment_preview_height_tall_wide)
@@ -585,8 +549,7 @@
int x = 0;
while (view != null) {
x += (int) view.getX();
- ViewParent parent = view.getParent();
- view = parent != null ? (View) parent : null;
+ view = (View) view.getParent();
}
return x;
}
@@ -598,8 +561,7 @@
int y = 0;
while (view != null) {
y += (int) view.getY();
- ViewParent parent = view.getParent();
- view = parent != null ? (View) parent : null;
+ view = (View) view.getParent();
}
return y;
}
diff --git a/src/com/android/mail/browse/ConversationItemViewModel.java b/src/com/android/mail/browse/ConversationItemViewModel.java
index ad6c0d8..10a0b6c 100644
--- a/src/com/android/mail/browse/ConversationItemViewModel.java
+++ b/src/com/android/mail/browse/ConversationItemViewModel.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.graphics.Bitmap;
-import android.net.Uri;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.StaticLayout;
@@ -34,6 +33,7 @@
import com.android.mail.providers.Folder;
import com.android.mail.providers.MessageInfo;
import com.android.mail.providers.UIProvider;
+import com.android.mail.utils.FolderUri;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
import com.google.common.collect.Lists;
@@ -360,8 +360,9 @@
* Clear cached header model objects when the folder changes.
*/
public static void onFolderUpdated(Folder folder) {
- Uri old = sCachedModelsFolder != null ? sCachedModelsFolder.uri : Uri.EMPTY;
- Uri newUri = folder != null ? folder.uri : Uri.EMPTY;
+ final FolderUri old = sCachedModelsFolder != null
+ ? sCachedModelsFolder.folderUri : FolderUri.EMPTY;
+ final FolderUri newUri = folder != null ? folder.folderUri : FolderUri.EMPTY;
if (!old.equals(newUri)) {
sCachedModelsFolder = folder;
sConversationHeaderMap.evictAll();
diff --git a/src/com/android/mail/browse/ConversationViewAdapter.java b/src/com/android/mail/browse/ConversationViewAdapter.java
index 9f278ab..9f59f8c 100644
--- a/src/com/android/mail/browse/ConversationViewAdapter.java
+++ b/src/com/android/mail/browse/ConversationViewAdapter.java
@@ -29,6 +29,7 @@
import com.android.mail.ContactInfoSource;
import com.android.mail.FormattedDateBuilder;
import com.android.mail.R;
+import com.android.mail.ads.AdHeaderView;
import com.android.mail.browse.ConversationViewHeader.ConversationViewHeaderCallbacks;
import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
import com.android.mail.browse.SuperCollapsedBlock.OnClickListener;
@@ -74,10 +75,12 @@
private final VeiledAddressMatcher mMatcher;
public static final int VIEW_TYPE_CONVERSATION_HEADER = 0;
- public static final int VIEW_TYPE_MESSAGE_HEADER = 1;
- public static final int VIEW_TYPE_MESSAGE_FOOTER = 2;
- public static final int VIEW_TYPE_SUPER_COLLAPSED_BLOCK = 3;
- public static final int VIEW_TYPE_COUNT = 4;
+ public static final int VIEW_TYPE_AD_HEADER = 1;
+ public static final int VIEW_TYPE_AD_FOOTER = 2;
+ public static final int VIEW_TYPE_MESSAGE_HEADER = 3;
+ public static final int VIEW_TYPE_MESSAGE_FOOTER = 4;
+ public static final int VIEW_TYPE_SUPER_COLLAPSED_BLOCK = 5;
+ public static final int VIEW_TYPE_COUNT = 6;
public class ConversationHeaderItem extends ConversationOverlayItem {
public final Conversation mConversation;
@@ -119,6 +122,65 @@
}
+ public class AdHeaderItem extends ConversationOverlayItem {
+ public final Conversation mConversation;
+
+ private AdHeaderItem(Conversation conv) {
+ mConversation = conv;
+ }
+
+ @Override
+ public int getType() {
+ return VIEW_TYPE_AD_HEADER;
+ }
+
+ @Override
+ public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
+ final AdHeaderView headerView = (AdHeaderView) inflater.inflate(
+ R.layout.ad_header_view, parent, false);
+ headerView.bind(this);
+ headerView.setAdSubject(mConversation.subject);
+
+ return headerView;
+ }
+
+ @Override
+ public void bindView(View v, boolean measureOnly) {
+ final AdHeaderView header = (AdHeaderView) v;
+ header.bind(this);
+ }
+
+ @Override
+ public boolean isContiguous() {
+ return false;
+ }
+
+ }
+
+ public class AdFooterItem extends ConversationOverlayItem {
+
+ @Override
+ public int getType() {
+ return VIEW_TYPE_AD_FOOTER;
+ }
+
+ @Override
+ public View createView(Context context, LayoutInflater inflater, ViewGroup parent) {
+ return null;
+ }
+
+ @Override
+ public void bindView(View v, boolean measureOnly) {
+ // DO NOTHING
+ }
+
+ @Override
+ public boolean isContiguous() {
+ return true;
+ }
+
+ }
+
public static class MessageHeaderItem extends ConversationOverlayItem {
private final ConversationViewAdapter mAdapter;
@@ -407,6 +469,14 @@
return addItem(new ConversationHeaderItem(conv));
}
+ public int addAdHeader(Conversation conversation) {
+ return addItem(new AdHeaderItem(conversation));
+ }
+
+ public int addAdFooter() {
+ return addItem(new AdFooterItem());
+ }
+
public int addMessageHeader(ConversationMessage msg, boolean expanded, boolean showImages) {
return addItem(new MessageHeaderItem(this, msg, expanded, showImages));
}
diff --git a/src/com/android/mail/browse/EmailAddressSpan.java b/src/com/android/mail/browse/EmailAddressSpan.java
new file mode 100644
index 0000000..cbf5ec4
--- /dev/null
+++ b/src/com/android/mail/browse/EmailAddressSpan.java
@@ -0,0 +1,51 @@
+/*
+ * 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.browse;
+
+import android.text.TextPaint;
+import android.text.style.URLSpan;
+import android.view.View;
+
+import com.android.mail.compose.ComposeActivity;
+import com.android.mail.providers.Account;
+
+public class EmailAddressSpan extends URLSpan {
+
+ private final Account mAccount;
+ private final String mEmailAddress;
+
+ public EmailAddressSpan(Account account, String emailAddress) {
+ super("mailto:" + emailAddress);
+ mAccount = account;
+ mEmailAddress = emailAddress;
+ }
+
+ @Override
+ public void onClick(View view) {
+ ComposeActivity.composeToAddress(view.getContext(), mAccount, mEmailAddress);
+ }
+
+ /**
+ * Makes the text in the link color and not underlined.
+ */
+ @Override
+ public void updateDrawState(TextPaint ds) {
+ ds.setColor(ds.linkColor);
+ ds.setUnderlineText(false);
+ }
+}
diff --git a/src/com/android/mail/browse/EmlMessageViewFragment.java b/src/com/android/mail/browse/EmlMessageViewFragment.java
index 17b7a0c..d2824bc 100644
--- a/src/com/android/mail/browse/EmlMessageViewFragment.java
+++ b/src/com/android/mail/browse/EmlMessageViewFragment.java
@@ -191,7 +191,7 @@
@Override
public ConversationAccountController getConversationAccountController() {
- return null;
+ return (EmlViewerActivity) getActivity();
}
@Override
diff --git a/src/com/android/mail/browse/EmlViewerActivity.java b/src/com/android/mail/browse/EmlViewerActivity.java
index a73c0f8..1e0652d 100644
--- a/src/com/android/mail/browse/EmlViewerActivity.java
+++ b/src/com/android/mail/browse/EmlViewerActivity.java
@@ -41,7 +41,8 @@
import com.android.mail.utils.MimeType;
import com.android.mail.utils.Utils;
-public class EmlViewerActivity extends Activity implements FeedbackEnabledActivity {
+public class EmlViewerActivity extends Activity implements FeedbackEnabledActivity,
+ ConversationAccountController {
public static final String EXTRA_ACCOUNT_URI = "extra-account-uri";
private static final String LOG_TAG = LogTag.getLogTag();
@@ -153,6 +154,11 @@
return this;
}
+ @Override
+ public Account getAccount() {
+ return mAccount;
+ }
+
private class AccountLoadCallbacks
implements LoaderManager.LoaderCallbacks<ObjectCursor<Account>> {
diff --git a/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java b/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.java
new file mode 100644
index 0000000..1138e78
--- /dev/null
+++ b/src/com/android/mail/browse/MessageHeaderDetailsDialogFragment.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.browse;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+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 java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@link DialogFragment} used by secure conversation views to display
+ * the expanded message details as a dialog.
+ */
+public class MessageHeaderDetailsDialogFragment extends DialogFragment {
+
+ private static final String ARG_ACCOUNT = "account";
+ private static final String ARG_ADDRESS_CACHE = "addresses";
+ private static final String ARG_FROM = "from";
+ private static final String ARG_REPLY_TO = "replyto";
+ private static final String ARG_TO = "to";
+ private static final String ARG_CC = "cc";
+ private static final String ARG_BCC = "bcc";
+
+ /**
+ * Creates a new {@link MessageHeaderDetailsDialogFragment}.
+ * @param addressCache a mapping of RFC822 addresses as strings to {@link Address}.
+ * @param account {@link Account} used as the from address for any messages created
+ * by tapping an email address.
+ * @param from from addresses for the message
+ * @param replyTo replyTo addresses for the message
+ * @param to to addresses for the message
+ * @param cc cc addresses for the message
+ * @param bcc bcc addresses for the message
+ * @return a newly created {@link MessageHeaderDetailsDialogFragment}
+ */
+ public static MessageHeaderDetailsDialogFragment newInstance(
+ Map<String, Address> addressCache, Account account, String[] from, String[] replyTo,
+ String[] to, String[] cc, String[] bcc) {
+ final MessageHeaderDetailsDialogFragment f = new MessageHeaderDetailsDialogFragment();
+
+ // Supply needed items as arguments
+ final Bundle args = new Bundle(7);
+ args.putParcelable(ARG_ACCOUNT, account);
+
+ final Bundle addresses = new Bundle();
+ addAddressesToBundle(addresses, addressCache, from);
+ addAddressesToBundle(addresses, addressCache, replyTo);
+ addAddressesToBundle(addresses, addressCache, to);
+ addAddressesToBundle(addresses, addressCache, cc);
+ addAddressesToBundle(addresses, addressCache, bcc);
+ args.putBundle(ARG_ADDRESS_CACHE, addresses);
+
+ args.putStringArray(ARG_FROM, from);
+ args.putStringArray(ARG_REPLY_TO, replyTo);
+ args.putStringArray(ARG_TO, to);
+ args.putStringArray(ARG_CC, cc);
+ args.putStringArray(ARG_BCC, bcc);
+ f.setArguments(args);
+
+ return f;
+ }
+
+ private static void addAddressesToBundle(
+ Bundle addresses, Map<String, Address> addressCache, String[] emails) {
+ for (final String email : emails) {
+ addresses.putParcelable(email, MessageHeaderView.getAddress(addressCache, email));
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(final Bundle onSavedInstanceState) {
+ final Context context = getActivity();
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ final View expandedDetails = MessageHeaderView.inflateExpandedDetails(
+ LayoutInflater.from(context));
+
+ final Bundle args = getArguments();
+
+ // turn bundle back into Map<String, Address>
+ final Bundle addresses = args.getBundle(ARG_ADDRESS_CACHE);
+ final Map<String, Address> addressCache = new HashMap<String, Address>();
+ for (String email : addresses.keySet()) {
+ addressCache.put(email, (Address) addresses.getParcelable(email));
+ }
+
+ MessageHeaderView.renderExpandedDetails(getResources(), expandedDetails, null,
+ addressCache, (Account) args.getParcelable(ARG_ACCOUNT), null,
+ args.getStringArray(ARG_FROM), args.getStringArray(ARG_REPLY_TO),
+ args.getStringArray(ARG_TO), args.getStringArray(ARG_CC),
+ args.getStringArray(ARG_BCC));
+
+ expandedDetails.findViewById(R.id.details_expander)
+ .setVisibility(View.GONE);
+ builder.setView(expandedDetails)
+ .setCancelable(true)
+ .setTitle(context.getString(R.string.message_details_title));
+ return builder.create();
+ }
+}
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index 72987d3..24d83bc 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -16,7 +16,8 @@
package com.android.mail.browse;
-import android.app.AlertDialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
import android.content.AsyncQueryHandler;
import android.content.Context;
import android.content.res.Resources;
@@ -27,8 +28,10 @@
import android.provider.ContactsContract;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.StyleSpan;
+import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -103,6 +106,8 @@
public static final boolean ENABLE_REPORT_RENDERING_PROBLEM =
MailPrefs.SHOW_EXPERIMENTAL_PREFS;
+ private static final String DETAILS_DIALOG_TAG = "details-dialog";
+
private MessageHeaderViewCallbacks mCallbacks;
private ViewGroup mUpperHeaderView;
@@ -209,7 +214,7 @@
private int mExpandMode = DEFAULT_MODE;
- private AlertDialog mDetailsPopup;
+ private DialogFragment mDetailsPopup;
private VeiledAddressMatcher mVeiledMatcher;
@@ -234,6 +239,8 @@
boolean supportsMessageTransforms();
String getMessageTransforms(Message msg);
+
+ FragmentManager getFragmentManager();
}
public MessageHeaderView(Context context) {
@@ -498,11 +505,11 @@
return item == mMessageHeaderItem;
}
- private Address getAddress(String emailStr) {
+ public Address getAddress(String emailStr) {
return getAddress(mAddressCache, emailStr);
}
- private static Address getAddress(Map<String, Address> cache, String emailStr) {
+ public static Address getAddress(Map<String, Address> cache, String emailStr) {
Address addr = null;
synchronized (cache) {
if (cache != null) {
@@ -719,67 +726,6 @@
}
/**
- * Render an email list for the expanded message details view.
- * @param headerId
- * @param detailsId
- * @param emails
- * @param showViaDomain
- * @param rootView
- */
- private void renderEmailList(int headerId, int detailsId, String[] emails,
- boolean showViaDomain, View rootView) {
- if (emails == null || emails.length == 0) {
- return;
- }
- final String[] formattedEmails = new String[emails.length];
- final Resources res = getResources();
- for (int i = 0; i < emails.length; i++) {
- final Address email = getAddress(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
- // alternate layout
- final boolean isVeiledAddress = mVeiledMatcher != null &&
- mVeiledMatcher.isVeiledAddress(address);
- final String addressShown;
- if (isVeiledAddress) {
- // Add the warning at the end of the name, and remove the address. The alternate
- // text cannot be put in the address part, because the address is made into a link,
- // and the alternate human-readable text is not a link.
- addressShown = "";
- if (TextUtils.isEmpty(name)) {
- // Empty name and we will block out the address. Let's write something more
- // readable.
- name = res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT_UNKNOWN_PERSON);
- } else {
- name = name + res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT);
- }
- } else {
- addressShown = address;
- }
- if (name == null || name.length() == 0) {
- formattedEmails[i] = addressShown;
- } else {
- // The one downside to having the showViaDomain here is that
- // if the sender does not have a name, it will not show the via info
- if (showViaDomain) {
- formattedEmails[i] = res.getString(
- R.string.address_display_format_with_via_domain,
- name, addressShown, mMessage.viaDomain);
- } else {
- formattedEmails[i] = res.getString(R.string.address_display_format,
- name, addressShown);
- }
- }
- }
-
- rootView.findViewById(headerId).setVisibility(VISIBLE);
- final TextView detailsText = (TextView) rootView.findViewById(detailsId);
- detailsText.setText(TextUtils.join("\n", formattedEmails));
- detailsText.setVisibility(VISIBLE);
- }
-
- /**
* Utility class to build a list of recipient lists.
*/
private static class RecipientListsBuilder {
@@ -1320,45 +1266,127 @@
private boolean ensureExpandedDetailsView() {
boolean viewCreated = false;
if (mExpandedDetailsView == null) {
- View v = mInflater.inflate(R.layout.conversation_message_details_header_expanded, null,
- false);
+ View v = inflateExpandedDetails(mInflater);
v.setOnClickListener(this);
mExpandedDetailsView = (ViewGroup) v;
viewCreated = true;
}
if (!mExpandedDetailsValid) {
- renderEmailList(R.id.from_heading, R.id.from_details, mFrom, mMessage.viaDomain != null,
- mExpandedDetailsView);
- renderEmailList(R.id.replyto_heading, R.id.replyto_details, mReplyTo, false,
- mExpandedDetailsView);
- renderEmailList(R.id.to_heading, R.id.to_details, mTo, false, mExpandedDetailsView);
- renderEmailList(R.id.cc_heading, R.id.cc_details, mCc, false, mExpandedDetailsView);
- renderEmailList(R.id.bcc_heading, R.id.bcc_details, mBcc, false, mExpandedDetailsView);
+ renderExpandedDetails(getResources(), mExpandedDetailsView, mMessage.viaDomain,
+ mAddressCache, getAccount(), mVeiledMatcher, mFrom, mReplyTo, mTo, mCc, mBcc);
mExpandedDetailsValid = true;
}
return viewCreated;
}
+ public static View inflateExpandedDetails(LayoutInflater inflater) {
+ return inflater.inflate(R.layout.conversation_message_details_header_expanded, null,
+ false);
+ }
+
+ public static void renderExpandedDetails(Resources res, View detailsView,
+ String viaDomain, Map<String, Address> addressCache, Account account,
+ VeiledAddressMatcher veiledMatcher, String[] from, String[] replyTo,
+ String[] to, String[] cc, String[] bcc) {
+ renderEmailList(res, R.id.from_heading, R.id.from_details, from, viaDomain,
+ detailsView, addressCache, account, veiledMatcher);
+ renderEmailList(res, R.id.replyto_heading, R.id.replyto_details, replyTo, viaDomain,
+ detailsView, addressCache, account, veiledMatcher);
+ renderEmailList(res, R.id.to_heading, R.id.to_details, to, viaDomain,
+ detailsView, addressCache, account, veiledMatcher);
+ renderEmailList(res, R.id.cc_heading, R.id.cc_details, cc, viaDomain,
+ detailsView, addressCache, account, veiledMatcher);
+ renderEmailList(res, R.id.bcc_heading, R.id.bcc_details, bcc, viaDomain,
+ detailsView, addressCache, account, veiledMatcher);
+ }
+
+ /**
+ * Render an email list for the expanded message details view.
+ */
+ private static void renderEmailList(Resources res, int headerId, int detailsId,
+ String[] emails, String viaDomain, View rootView,
+ Map<String, Address> addressCache, Account account,
+ VeiledAddressMatcher veiledMatcher) {
+ if (emails == null || emails.length == 0) {
+ return;
+ }
+ final String[] formattedEmails = new String[emails.length];
+ for (int i = 0; i < emails.length; i++) {
+ final Address email = 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
+ // alternate layout
+ final boolean isVeiledAddress = veiledMatcher != null &&
+ veiledMatcher.isVeiledAddress(address);
+ final String addressShown;
+ if (isVeiledAddress) {
+ // Add the warning at the end of the name, and remove the address. The alternate
+ // text cannot be put in the address part, because the address is made into a link,
+ // and the alternate human-readable text is not a link.
+ addressShown = "";
+ if (TextUtils.isEmpty(name)) {
+ // Empty name and we will block out the address. Let's write something more
+ // readable.
+ name = res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT_UNKNOWN_PERSON);
+ } else {
+ name = name + res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT);
+ }
+ } else {
+ addressShown = address;
+ }
+ if (name == null || name.length() == 0) {
+ formattedEmails[i] = addressShown;
+ } else {
+ // The one downside to having the showViaDomain here is that
+ // if the sender does not have a name, it will not show the via info
+ if (viaDomain != null) {
+ formattedEmails[i] = res.getString(
+ R.string.address_display_format_with_via_domain,
+ name, addressShown, viaDomain);
+ } else {
+ formattedEmails[i] = res.getString(R.string.address_display_format,
+ name, addressShown);
+ }
+ }
+ }
+
+ rootView.findViewById(headerId).setVisibility(VISIBLE);
+ final TextView detailsText = (TextView) rootView.findViewById(detailsId);
+ detailsText.setText(TextUtils.join("\n", formattedEmails));
+ stripUnderlines(detailsText, account);
+ detailsText.setVisibility(VISIBLE);
+ }
+
+ private static void stripUnderlines(TextView textView, Account account) {
+ final Spannable spannable = (Spannable) textView.getText();
+ final URLSpan[] urls = textView.getUrls();
+
+ for (URLSpan span : urls) {
+ final int start = spannable.getSpanStart(span);
+ final int end = spannable.getSpanEnd(span);
+ spannable.removeSpan(span);
+ span = new EmailAddressSpan(account, span.getURL().substring(7));
+ spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+
private void showDetailsPopup() {
- ensureExpandedDetailsView();
+ final FragmentManager manager = mCallbacks.getFragmentManager();
+ mDetailsPopup = (DialogFragment) manager.findFragmentByTag(DETAILS_DIALOG_TAG);
if (mDetailsPopup == null) {
- AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
- mExpandedDetailsView.findViewById(R.id.details_expander)
- .setVisibility(View.GONE);
- builder.setView(mExpandedDetailsView)
- .setCancelable(true)
- .setTitle(getContext().getString(R.string.message_details_title));
- mDetailsPopup = builder.show();
- } else {
- mDetailsPopup.show();
+ mDetailsPopup = MessageHeaderDetailsDialogFragment.newInstance(
+ mAddressCache, getAccount(), mFrom, mReplyTo, mTo, mCc, mBcc);
+ mDetailsPopup.show(manager, DETAILS_DIALOG_TAG);
}
}
private void hideDetailsPopup() {
if (mDetailsPopup != null) {
- mDetailsPopup.hide();
+ mDetailsPopup.dismiss();
+ mDetailsPopup = null;
}
}
diff --git a/src/com/android/mail/browse/SwipeableConversationItemView.java b/src/com/android/mail/browse/SwipeableConversationItemView.java
index a675b8d..cd98af0 100644
--- a/src/com/android/mail/browse/SwipeableConversationItemView.java
+++ b/src/com/android/mail/browse/SwipeableConversationItemView.java
@@ -26,6 +26,7 @@
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.ui.AnimatedAdapter;
+import com.android.mail.ui.AnimatedAdapter.ConversationListListener;
import com.android.mail.ui.ControllableActivity;
import com.android.mail.ui.ConversationSelectionSet;
@@ -52,10 +53,13 @@
}
public void bind(Conversation conversation, ControllableActivity activity,
+ final ConversationListListener conversationListListener,
ConversationSelectionSet set, Folder folder, int checkboxOrSenderImage,
- boolean swipeEnabled, boolean priorityArrowsEnabled, AnimatedAdapter animatedAdapter) {
- mConversationItemView.bind(conversation, activity, set, folder, checkboxOrSenderImage,
- swipeEnabled, priorityArrowsEnabled, animatedAdapter);
+ boolean swipeEnabled, boolean priorityArrowsEnabled, AnimatedAdapter animatedAdapter,
+ final int adapterPosition) {
+ mConversationItemView.bind(conversation, activity, conversationListListener, set, folder,
+ checkboxOrSenderImage, swipeEnabled, priorityArrowsEnabled, animatedAdapter,
+ adapterPosition);
}
public void startUndoAnimation(AnimatorListener listener, boolean swipe) {
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index fa31833..844696e 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -202,7 +202,7 @@
private static final String EXTRA_SELECTED_REPLY_FROM_ACCOUNT = "replyFromAccount";
private static final String EXTRA_REQUEST_ID = "requestId";
private static final String EXTRA_FOCUS_SELECTION_START = "focusSelectionStart";
- private static final String EXTRA_FOCUS_SELECTION_END = null;
+ private static final String EXTRA_FOCUS_SELECTION_END = "focusSelectionEnd";
private static final String EXTRA_MESSAGE = "extraMessage";
private static final int REFERENCE_MESSAGE_LOADER = 0;
private static final int LOADER_ACCOUNT_CURSOR = 1;
@@ -296,6 +296,13 @@
/**
* Can be called from a non-UI thread.
*/
+ public static void composeToAddress(Context launcher, Account account, String toAddress) {
+ launch(launcher, account, null, COMPOSE, toAddress, null);
+ }
+
+ /**
+ * Can be called from a non-UI thread.
+ */
public static Intent createReplyIntent(final Context launcher, final Account account,
final Uri messageUri, final boolean isReplyAll) {
return createActionIntent(launcher, account, messageUri, isReplyAll ? REPLY_ALL : REPLY);
@@ -313,6 +320,13 @@
final Uri messageUri, final int action) {
final Intent intent = new Intent(launcher, ComposeActivity.class);
+ updateActionIntent(account, messageUri, action, intent);
+
+ return intent;
+ }
+
+ @VisibleForTesting
+ static Intent updateActionIntent(Account account, Uri messageUri, int action, Intent intent) {
intent.putExtra(EXTRA_FROM_EMAIL_TASK, true);
intent.putExtra(EXTRA_ACTION, action);
intent.putExtra(Utils.EXTRA_ACCOUNT, account);
@@ -834,9 +848,6 @@
message.setFrom(selectedReplyFromAccount != null ? selectedReplyFromAccount.address
: mAccount != null ? mAccount.name : null);
message.draftType = getDraftType(mode);
- message.setTo(formatSenders(mTo.getText().toString()));
- message.setCc(formatSenders(mCc.getText().toString()));
- message.setBcc(formatSenders(mBcc.getText().toString()));
return message;
}
@@ -920,10 +931,10 @@
}
/**
- * Given an account and which email address the message was sent to,
+ * Given an account and the message we're replying to,
* return who the message should be sent from.
* @param account Account in which the message arrived.
- * @param sentTo Email address to which the message was sent.
+ * @param refMessage Message to analyze for account selection
* @return the address from which to reply.
*/
public ReplyFromAccount getReplyFromAccount(Account account, Message refMessage) {
@@ -936,8 +947,8 @@
// all the message recipients and find one that matches
// a custom from or account.
List<String> allRecipients = new ArrayList<String>();
- allRecipients.addAll(Arrays.asList(refMessage.getToAddresses()));
- allRecipients.addAll(Arrays.asList(refMessage.getCcAddresses()));
+ allRecipients.addAll(Arrays.asList(refMessage.getToAddressesUnescaped()));
+ allRecipients.addAll(Arrays.asList(refMessage.getCcAddressesUnescaped()));
return getMatchingRecipient(account, allRecipients);
}
}
@@ -1175,10 +1186,10 @@
mDraftId = message.id;
mSubject.setText(message.subject);
mForward = message.draftType == UIProvider.DraftType.FORWARD;
- final List<String> toAddresses = Arrays.asList(message.getToAddresses());
+ final List<String> toAddresses = Arrays.asList(message.getToAddressesUnescaped());
addToAddresses(toAddresses);
- addCcAddresses(Arrays.asList(message.getCcAddresses()), toAddresses);
- addBccAddresses(Arrays.asList(message.getBccAddresses()));
+ addCcAddresses(Arrays.asList(message.getCcAddressesUnescaped()), toAddresses);
+ addBccAddresses(Arrays.asList(message.getBccAddressesUnescaped()));
if (message.hasAttachments) {
List<Attachment> attachments = message.getAttachments();
for (Attachment a : attachments) {
@@ -1565,9 +1576,11 @@
initReplyRecipients(refMessage, action);
}
+ // TODO: This should be private. This method shouldn't be used by ComposeActivityTests, as
+ // it doesn't setup the state of the activity correctly
@VisibleForTesting
void initReplyRecipients(final Message refMessage, final int action) {
- String[] sentToAddresses = refMessage.getToAddresses();
+ String[] sentToAddresses = refMessage.getToAddressesUnescaped();
final Collection<String> toAddresses;
String replytoAddress = refMessage.getReplyTo();
// If there is no reply to address, the reply to address is the sender.
@@ -1587,7 +1600,7 @@
toAddresses = initToRecipients(refMessage.getFrom(), replytoAddress, sentToAddresses);
addToAddresses(toAddresses);
addRecipients(ccAddresses, sentToAddresses);
- addRecipients(ccAddresses, refMessage.getCcAddresses());
+ addRecipients(ccAddresses, refMessage.getCcAddressesUnescaped());
addCcAddresses(ccAddresses, toAddresses);
}
}
@@ -1718,7 +1731,6 @@
* A recipient matches this account if it has the same address as the
* currently selected account OR one of the custom from addresses associated
* with the currently selected account.
- * @param accountAddress currently selected account
* @param recipientAddress address we are comparing with the currently selected account
* @return
*/
diff --git a/src/com/android/mail/photomanager/PhotoManager.java b/src/com/android/mail/photomanager/PhotoManager.java
index b3037fc..0b937cb 100644
--- a/src/com/android/mail/photomanager/PhotoManager.java
+++ b/src/com/android/mail/photomanager/PhotoManager.java
@@ -468,19 +468,15 @@
}
case MESSAGE_PHOTOS_LOADED: {
- if (!mPaused) {
- processLoadedImages();
- }
+ processLoadedImages();
if (DEBUG) dumpStats();
return true;
}
case MESSAGE_PHOTO_LOADING: {
- if (!mPaused) {
- final int hashcode = msg.arg1;
- final Request request = mPendingRequests.get(hashcode);
- onImageLoadStarted(request);
- }
+ final int hashcode = msg.arg1;
+ final Request request = mPendingRequests.get(hashcode);
+ onImageLoadStarted(request);
return true;
}
}
@@ -494,9 +490,9 @@
private void processLoadedImages() {
Utils.traceBeginSection("process loaded images");
final List<Integer> toRemove = Lists.newArrayList();
- for (Integer hash : mPendingRequests.keySet()) {
- Request request = mPendingRequests.get(hash);
- boolean loaded = loadCachedPhoto(request, true);
+ for (final Integer hash : mPendingRequests.keySet()) {
+ final Request request = mPendingRequests.get(hash);
+ final boolean loaded = loadCachedPhoto(request, true);
// Request can go through multiple attempts if the LoaderThread fails to load any
// images for it, or if the images it loads are evicted from the cache before we
// could access them in the main thread.
@@ -504,11 +500,11 @@
toRemove.add(hash);
}
}
- for (Integer key : toRemove) {
+ for (final Integer key : toRemove) {
mPendingRequests.remove(key);
}
- if (!mPendingRequests.isEmpty()) {
+ if (!mPaused && !mPendingRequests.isEmpty()) {
LogUtils.d(TAG, "Finished loading batch. %d still have to be loaded.",
mPendingRequests.size());
requestLoading();
diff --git a/src/com/android/mail/preferences/MailPrefs.java b/src/com/android/mail/preferences/MailPrefs.java
index 985dda4..269c7b4 100644
--- a/src/com/android/mail/preferences/MailPrefs.java
+++ b/src/com/android/mail/preferences/MailPrefs.java
@@ -79,6 +79,9 @@
public static final String DISPLAY_IMAGES = "display_images";
public static final String DISPLAY_IMAGES_PATTERNS = "display_sender_images_patterns_set";
+
+ public static final String SHOW_SENDER_IMAGES = "conversation-list-sender-image";
+
public static final ImmutableSet<String> BACKUP_KEYS =
new ImmutableSet.Builder<String>()
.add(DEFAULT_REPLY_ALL)
@@ -86,6 +89,7 @@
.add(REMOVAL_ACTION)
.add(DISPLAY_IMAGES)
.add(DISPLAY_IMAGES_PATTERNS)
+ .add(SHOW_SENDER_IMAGES)
.build();
}
@@ -351,4 +355,15 @@
editor.putStringSet(PreferenceKeys.DISPLAY_IMAGES_PATTERNS, Collections.EMPTY_SET);
editor.apply();
}
+
+
+ public void setShowSenderImages(boolean enable) {
+ getEditor().putBoolean(PreferenceKeys.SHOW_SENDER_IMAGES, enable).apply();
+ notifyBackupPreferenceChanged();
+ }
+
+ public boolean getShowSenderImages() {
+ final SharedPreferences sharedPreferences = getSharedPreferences();
+ return sharedPreferences.getBoolean(PreferenceKeys.SHOW_SENDER_IMAGES, true);
+ }
}
diff --git a/src/com/android/mail/preferences/VersionedPrefs.java b/src/com/android/mail/preferences/VersionedPrefs.java
index bc50d98..81eabde 100644
--- a/src/com/android/mail/preferences/VersionedPrefs.java
+++ b/src/com/android/mail/preferences/VersionedPrefs.java
@@ -51,7 +51,7 @@
* The current version number for {@link SharedPreferences}. This is a constant for all
* applications based on UnifiedEmail.
*/
- protected static final int CURRENT_VERSION_NUMBER = 2;
+ protected static final int CURRENT_VERSION_NUMBER = 3;
protected static final String LOG_TAG = LogTag.getLogTag();
diff --git a/src/com/android/mail/providers/Address.java b/src/com/android/mail/providers/Address.java
index 595568c..edd2db1 100644
--- a/src/com/android/mail/providers/Address.java
+++ b/src/com/android/mail/providers/Address.java
@@ -15,6 +15,12 @@
*/
package com.android.mail.providers;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.text.util.Rfc822Token;
+import android.text.util.Rfc822Tokenizer;
+
import com.android.common.Rfc822Validator;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
@@ -24,10 +30,6 @@
import org.apache.james.mime4j.codec.EncoderUtil;
import org.apache.james.mime4j.decoder.DecoderUtil;
-import android.text.TextUtils;
-import android.text.util.Rfc822Token;
-import android.text.util.Rfc822Tokenizer;
-
import java.util.ArrayList;
import java.util.regex.Pattern;
@@ -42,7 +44,7 @@
* Name and comment part should be MIME/base64 encoded in header if necessary.
*
*/
-public class Address {
+public class Address implements Parcelable {
public static final String ADDRESS_DELIMETER = ",";
/**
* Address part, in the form local_part@domain_part. No surrounding angle brackets.
@@ -81,6 +83,8 @@
setAddress(address);
}
+
+
/**
* Returns a simplified string for this e-mail address.
* When a name is known, it will return the first token of that name. Otherwise, it will
@@ -512,4 +516,32 @@
return address + LIST_DELIMITER_PERSONAL + personal;
}
}
+
+ public static final Creator<Address> CREATOR = new Creator<Address>() {
+ @Override
+ public Address createFromParcel(Parcel parcel) {
+ return new Address(parcel);
+ }
+
+ @Override
+ public Address[] newArray(int size) {
+ return new Address[size];
+ }
+ };
+
+ public Address(Parcel in) {
+ setName(in.readString());
+ setAddress(in.readString());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mName);
+ out.writeString(mAddress);
+ }
}
diff --git a/src/com/android/mail/providers/Conversation.java b/src/com/android/mail/providers/Conversation.java
index e936ed5..741c669 100644
--- a/src/com/android/mail/providers/Conversation.java
+++ b/src/com/android/mail/providers/Conversation.java
@@ -522,6 +522,7 @@
fl = response.getParcelable(key);
} else {
// legacy fallback
+ // TODO: delete this once Email supports the respond call
fl = FolderList.fromBlob(
cursor.getBlob(UIProvider.CONVERSATION_RAW_FOLDERS_COLUMN));
}
diff --git a/src/com/android/mail/providers/Folder.java b/src/com/android/mail/providers/Folder.java
index 77c69ae..c1ddf00 100644
--- a/src/com/android/mail/providers/Folder.java
+++ b/src/com/android/mail/providers/Folder.java
@@ -31,6 +31,7 @@
import com.android.mail.content.CursorCreator;
import com.android.mail.content.ObjectCursorLoader;
import com.android.mail.providers.UIProvider.FolderType;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
@@ -79,7 +80,7 @@
/**
* The content provider URI that returns this folder for this account.
*/
- public Uri uri;
+ public FolderUri folderUri;
/**
* The human visible name for this folder.
@@ -201,7 +202,7 @@
final long lastMessageTimestamp) {
this.id = id;
this.persistentId = persistentId;
- this.uri = uri;
+ this.folderUri = new FolderUri(uri);
this.name = name;
this.capabilities = capabilities;
this.hasChildren = hasChildren;
@@ -234,7 +235,8 @@
public Folder(Cursor cursor) {
id = cursor.getInt(UIProvider.FOLDER_ID_COLUMN);
persistentId = cursor.getString(UIProvider.FOLDER_PERSISTENT_ID_COLUMN);
- uri = Uri.parse(cursor.getString(UIProvider.FOLDER_URI_COLUMN));
+ folderUri =
+ new FolderUri(Uri.parse(cursor.getString(UIProvider.FOLDER_URI_COLUMN)));
name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN);
capabilities = cursor.getInt(UIProvider.FOLDER_CAPABILITIES_COLUMN);
// 1 for true, 0 for false.
@@ -290,7 +292,7 @@
public Folder(Parcel in, ClassLoader loader) {
id = in.readInt();
persistentId = in.readString();
- uri = in.readParcelable(loader);
+ folderUri = new FolderUri((Uri) in.readParcelable(loader));
name = in.readString();
capabilities = in.readInt();
// 1 for true, 0 for false.
@@ -326,7 +328,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(persistentId);
- dest.writeParcelable(uri, 0);
+ dest.writeParcelable(folderUri != null ? folderUri.fullUri : null, 0);
dest.writeString(name);
dest.writeInt(capabilities);
// 1 for true, 0 for false.
@@ -371,7 +373,7 @@
public static HashMap<Uri, Folder> hashMapForFolders(List<Folder> rawFolders) {
final HashMap<Uri, Folder> folders = new HashMap<Uri, Folder>();
for (Folder f : rawFolders) {
- folders.put(f.uri, f);
+ folders.put(f.folderUri.getComparisonUri(), f);
}
return folders;
}
@@ -421,12 +423,12 @@
if (o == null || !(o instanceof Folder)) {
return false;
}
- return Objects.equal(uri, ((Folder) o).uri);
+ return Objects.equal(folderUri, ((Folder) o).folderUri);
}
@Override
public int hashCode() {
- return uri == null ? 0 : uri.hashCode();
+ return folderUri == null ? 0 : folderUri.hashCode();
}
@Override
@@ -436,7 +438,7 @@
sb.append(id);
if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
sb.append(", uri=");
- sb.append(uri);
+ sb.append(folderUri);
sb.append(", name=");
sb.append(name);
}
@@ -521,7 +523,7 @@
final String[] folderUris = new String[folders.size()];
int i = 0;
for (Folder folder : folders) {
- folderUris[i] = folder.uri.toString();
+ folderUris[i] = folder.folderUri.toString();
i++;
}
return folderUris;
@@ -621,7 +623,7 @@
}
f.id = id;
int index = 1;
- f.uri = Folder.getValidUri(split[index++]);
+ f.folderUri = new FolderUri(Folder.getValidUri(split[index++]));
f.name = split[index++];
f.hasChildren = Integer.parseInt(split[index++]) != 0;
f.capabilities = Integer.parseInt(split[index++]);
diff --git a/src/com/android/mail/providers/FolderWatcher.java b/src/com/android/mail/providers/FolderWatcher.java
index 8c0b1d3..4fb6474 100644
--- a/src/com/android/mail/providers/FolderWatcher.java
+++ b/src/com/android/mail/providers/FolderWatcher.java
@@ -220,7 +220,7 @@
return;
}
final Folder f = data.getModel();
- final Uri uri = f.uri;
+ final Uri uri = f.folderUri.getComparisonUri();
final int unreadCount = f.unreadCount;
final Folder previousFolder = mInbox.get(uri);
final boolean unreadCountChanged = previousFolder == null
diff --git a/src/com/android/mail/providers/MailAppProvider.java b/src/com/android/mail/providers/MailAppProvider.java
index 23c8965..97367a1 100644
--- a/src/com/android/mail/providers/MailAppProvider.java
+++ b/src/com/android/mail/providers/MailAppProvider.java
@@ -232,7 +232,6 @@
* {@link ContentProvider#query()} for the specified uri. The content provider handling the
* query needs to handle the {@link UIProvider.ACCOUNTS_PROJECTION}
* Any changes to the underlying provider will automatically be reflected.
- * @param resolver
* @param accountsQueryUri
*/
private void addAccountsForUriAsync(Uri accountsQueryUri) {
@@ -266,17 +265,6 @@
mCursorLoaderMap.put(accountsQueryUri, accountsCursorLoader);
}
- public static void addAccount(Account account, Uri accountsQueryUri) {
- final MailAppProvider provider = getInstance();
- if (provider == null) {
- throw new IllegalStateException("MailAppProvider not intialized");
- }
- provider.addAccountImpl(account, accountsQueryUri, true /* notify */);
-
- // Cache the updated account list
- provider.cacheAccountList();
- }
-
private void addAccountImpl(Account account, Uri accountsQueryUri, boolean notify) {
addAccountImpl(account.uri, new AccountCacheEntry(account, accountsQueryUri));
diff --git a/src/com/android/mail/providers/Message.java b/src/com/android/mail/providers/Message.java
index 0b71c69..4594ae1 100644
--- a/src/com/android/mail/providers/Message.java
+++ b/src/com/android/mail/providers/Message.java
@@ -482,6 +482,10 @@
return mFromAddresses;
}
+ public String[] getFromAddressesUnescaped() {
+ return unescapeAddresses(getFromAddresses());
+ }
+
public synchronized String[] getToAddresses() {
if (mToAddresses == null) {
mToAddresses = tokenizeAddresses(mTo);
@@ -489,6 +493,10 @@
return mToAddresses;
}
+ public String[] getToAddressesUnescaped() {
+ return unescapeAddresses(getToAddresses());
+ }
+
public synchronized String[] getCcAddresses() {
if (mCcAddresses == null) {
mCcAddresses = tokenizeAddresses(mCc);
@@ -496,6 +504,10 @@
return mCcAddresses;
}
+ public String[] getCcAddressesUnescaped() {
+ return unescapeAddresses(getCcAddresses());
+ }
+
public synchronized String[] getBccAddresses() {
if (mBccAddresses == null) {
mBccAddresses = tokenizeAddresses(mBcc);
@@ -503,6 +515,10 @@
return mBccAddresses;
}
+ public String[] getBccAddressesUnescaped() {
+ return unescapeAddresses(getBccAddresses());
+ }
+
public synchronized String[] getReplyToAddresses() {
if (mReplyToAddresses == null) {
mReplyToAddresses = tokenizeAddresses(mReplyTo);
@@ -510,10 +526,24 @@
return mReplyToAddresses;
}
+ public String[] getReplyToAddressesUnescaped() {
+ return unescapeAddresses(getReplyToAddresses());
+ }
+
+ private static String[] unescapeAddresses(String[] escaped) {
+ final String[] unescaped = new String[escaped.length];
+ for (int i = 0; i < escaped.length; i++) {
+ final String escapeMore = escaped[i].replace("<", "<").replace(">", ">");
+ unescaped[i] = Html.fromHtml(escapeMore).toString();
+ }
+ return unescaped;
+ }
+
public static String[] tokenizeAddresses(String addresses) {
if (TextUtils.isEmpty(addresses)) {
return new String[0];
}
+
Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addresses);
String[] strings = new String[tokens.length];
for (int i = 0; i < tokens.length;i++) {
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index c6565bf..89b4034 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -125,6 +125,13 @@
public static final String LABEL_QUERY_PARAMETER = "label";
public static final String SEEN_QUERY_PARAMETER = "seen";
+ /**
+ * Query parameter that can be used to specify a parent for a the returned folder object from a
+ * query. When set, if a folder is returned that does not have a true parent, it will use this
+ * uri as its parent uri.
+ */
+ public static final String DEFAULT_PARENT_QUERY_PARAMETER = "defaultParent";
+
public static final Map<String, Class<?>> ACCOUNTS_COLUMNS_NO_CAPABILITIES =
new ImmutableMap.Builder<String, Class<?>>()
.put(AccountColumns._ID, Integer.class)
diff --git a/src/com/android/mail/providers/protos/mock/MockRespondMatrixCursor.java b/src/com/android/mail/providers/protos/mock/MockRespondMatrixCursor.java
new file mode 100644
index 0000000..1409f88
--- /dev/null
+++ b/src/com/android/mail/providers/protos/mock/MockRespondMatrixCursor.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2013, Google Inc.
+ *
+ * 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.providers.protos.mock;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+
+import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.MatrixCursorWithCachedColumns;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class MockRespondMatrixCursor extends MatrixCursorWithCachedColumns{
+ private static final String LOG_TAG = "MockProvider";
+
+ static final String MOCK_RESPOND_PREFIX = "respond_";
+
+ final List<Map<String, Object>> mResultList;
+
+ public MockRespondMatrixCursor(final String[] columnNames, final int initialCapacity,
+ List<Map<String, Object>> queryResults) {
+ super(columnNames, initialCapacity);
+ mResultList = queryResults;
+ }
+
+ @Override
+ public Bundle respond(Bundle request) {
+ final Bundle response = new Bundle();
+
+ final int pos = getPosition();
+ if (pos >= mResultList.size()) {
+ LogUtils.wtf(LOG_TAG, "Unexpected position");
+ return response;
+ }
+
+ final Map<String, Object> rowData = mResultList.get(pos);
+
+ // For each of the keys in the request, we want to see if there is a mock response for the
+ // request
+ final Set<String> bundleKeys = request.keySet();
+ for (String key : bundleKeys) {
+ final Object responseData = rowData.get(MOCK_RESPOND_PREFIX + key);
+ if (responseData != null) {
+ response.putParcelable(key, (Parcelable)responseData);
+ }
+ }
+
+ return response;
+ }
+}
diff --git a/src/com/android/mail/providers/protos/mock/MockUiProvider.java b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
index 1055b42..103f5d4 100644
--- a/src/com/android/mail/providers/protos/mock/MockUiProvider.java
+++ b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
@@ -21,31 +21,26 @@
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
-import android.os.Parcel;
import android.provider.BaseColumns;
import android.text.Html;
-import com.android.mail.providers.Account;
import com.android.mail.providers.ConversationInfo;
import com.android.mail.providers.Folder;
import com.android.mail.providers.FolderList;
-import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.MessageInfo;
import com.android.mail.providers.ReplyFromAccount;
-import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.UIProvider.AccountColumns;
import com.android.mail.providers.UIProvider.AccountColumns.SettingsColumns;
import com.android.mail.providers.UIProvider.AttachmentColumns;
import com.android.mail.providers.UIProvider.ConversationColumns;
+import com.android.mail.providers.UIProvider.ConversationCursorCommand;
import com.android.mail.providers.UIProvider.FolderCapabilities;
import com.android.mail.providers.UIProvider.FolderColumns;
import com.android.mail.providers.UIProvider.MessageColumns;
-import com.android.mail.utils.MatrixCursorWithCachedColumns;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -61,144 +56,130 @@
public static final String AUTHORITY = "com.android.mail.mockprovider";
+ private static final int NUM_ACCOUNTS = 5;
- static final String BASE_URI_STRING = "content://" + AUTHORITY;
private static final Uri MOCK_ACCOUNTS_URI = Uri.parse("content://" + AUTHORITY + "/accounts");
-
- public static final int NUM_MOCK_ACCOUNTS = 2;
-
// A map of query result for uris
- // TODO(pwestbro) read this map from an external
+ // TODO(pwestbro) read this map from an external file
private static Map<String, List<Map<String, Object>>> MOCK_QUERY_RESULTS = Maps.newHashMap();
+ private static void initializeAccount(int accountId,
+ Map<String, List<Map<String, Object>>> resultMap) {
+ final Map<String, Object> inboxfolderDetailsMap =
+ createFolderDetailsMap(0, accountId, "zero", true, 0, 2);
+ resultMap.put(inboxfolderDetailsMap.get(FolderColumns.URI).toString(),
+ ImmutableList.of(inboxfolderDetailsMap));
- public static void initializeMockProvider() {
- ImmutableMap.Builder<String, List<Map<String, Object>>> builder = ImmutableMap.builder();
+ final Map<String, Object> accountDetailsMap = createAccountDetailsMap(accountId,
+ (String)inboxfolderDetailsMap.get(FolderColumns.URI));
+ resultMap.put(((Uri) accountDetailsMap.get(AccountColumns.URI)).toString(),
+ ImmutableList.of(accountDetailsMap));
- // Add results for account list
- final List<Map<String, Object>> accountList = Lists.newArrayList();
- Map<String, Object> accountDetailsMap0;
- Map<String, Object> folderDetailsMap0 = createFolderDetailsMap(0, "zero", true, 0, 2);
- builder.put(folderDetailsMap0.get(FolderColumns.URI).toString(),
- ImmutableList.of(folderDetailsMap0));
- Map<String, Object> folderDetailsMap2 = createFolderDetailsMap(2, "two", 2, 2);
- // Account 0
- accountDetailsMap0 = createAccountDetailsMap(0, true,
- (String)folderDetailsMap0.get(FolderColumns.URI));
+ final Map<String, Object> secondFolderDetailsMap =
+ createFolderDetailsMap(2, accountId, "two", 2, 2);
+ resultMap.put(secondFolderDetailsMap.get(FolderColumns.URI).toString(),
+ ImmutableList.of(secondFolderDetailsMap));
- accountList.add(accountDetailsMap0);
- builder.put(((Uri) accountDetailsMap0.get(AccountColumns.URI)).toString(),
- ImmutableList.of(accountDetailsMap0));
+ resultMap.put(
+ inboxfolderDetailsMap.get(FolderColumns.CHILD_FOLDERS_LIST_URI).toString(),
+ ImmutableList.of(createFolderDetailsMap(10, accountId, "zeroChild0", 0, 0),
+ createFolderDetailsMap(11, accountId, "zeroChild1", 0, 0)));
- // Account 1
- Map<String, Object> accountDetailsMap1 = createAccountDetailsMap(1, true,
- (String)folderDetailsMap2.get(FolderColumns.URI));
- accountList.add(accountDetailsMap1);
-
- builder.put(((Uri) accountDetailsMap1.get(AccountColumns.URI)).toString(),
- ImmutableList.of(accountDetailsMap1));
-
- // Account 2
-
- Map<String, Object> accountDetailsMap2 = createAccountDetailsMap(2, true,
- (String)folderDetailsMap0.get(FolderColumns.URI));
- accountList.add(accountDetailsMap2);
- builder.put(((Uri) accountDetailsMap2.get(AccountColumns.URI)).toString(),
- ImmutableList.of(accountDetailsMap2));
-
- // Account 3
- Map<String, Object> accountDetailsMap3 = createAccountDetailsMap(3, true,
- (String)folderDetailsMap2.get(FolderColumns.URI));
- accountList.add(accountDetailsMap3);
- builder.put(((Uri) accountDetailsMap3.get(AccountColumns.URI)).toString(),
- ImmutableList.of(accountDetailsMap3));
-
- // Add the account list to the builder
- builder.put(getAccountsUri().toString(), accountList);
-
- builder.put(
- folderDetailsMap0.get(FolderColumns.CHILD_FOLDERS_LIST_URI).toString(),
- ImmutableList.of(createFolderDetailsMap(10, "zeroChild0", 0, 0),
- createFolderDetailsMap(11, "zeroChild1", 0, 0)));
-
-
- ArrayList<Map<String, Object>> conversations = new ArrayList<Map<String, Object>>();
+ final ArrayList<Map<String, Object>> conversations = new ArrayList<Map<String, Object>>();
for (int i = 0; i < 100; i++) {
- String name = "zeroConv"+i;
- conversations.add(createConversationDetailsMap(name.hashCode(),
- name, 1, 5, 2));
+ final String name = "zeroConv"+i;
+ conversations.add(createConversationDetailsMap(accountId, name.hashCode(),
+ name, 1, 5, i % 2));
}
- builder.put(folderDetailsMap0.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
+ resultMap.put(inboxfolderDetailsMap.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
conversations);
- Map<String, Object> message0 = createMessageDetailsMap("zeroConv0".hashCode(), "zeroConv0",
- 1, false);
- builder.put(message0.get(MessageColumns.URI).toString(), ImmutableList.of(message0));
- builder.put(conversations.get(0).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
+ final Map<String, Object> message0 =
+ createMessageDetailsMap(accountId, "zeroConv0".hashCode(), "zeroConv0", 1, false);
+ resultMap.put(message0.get(MessageColumns.URI).toString(), ImmutableList.of(message0));
+ resultMap.put(conversations.get(0).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
ImmutableList.of(message0));
- builder.put(message0.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
+ resultMap.put(message0.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
ImmutableList.of(createAttachmentDetailsMap(0, "zero")));
- Map<String, Object> message1 = createMessageDetailsMap("zeroConv1".hashCode(), "zeroConv1",
- 1, false);
- builder.put(message1.get(MessageColumns.URI).toString(), ImmutableList.of(message1));
- Map<String, Object> message1a = createMessageDetailsMap("zeroConv1a".hashCode(), "zeroConv1a",
- 2, false);
- builder.put(message1a.get(MessageColumns.URI).toString(), ImmutableList.of(message1a));
- builder.put(conversations.get(1).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
+ final Map<String, Object> message1 =
+ createMessageDetailsMap(accountId, "zeroConv1".hashCode(), "zeroConv1", 1, false);
+ resultMap.put(message1.get(MessageColumns.URI).toString(), ImmutableList.of(message1));
+ final Map<String, Object> message1a =
+ createMessageDetailsMap(accountId, "zeroConv1a".hashCode(), "zeroConv1a", 2, false);
+ resultMap.put(message1a.get(MessageColumns.URI).toString(), ImmutableList.of(message1a));
+ resultMap.put(conversations.get(1).get(ConversationColumns.MESSAGE_LIST_URI).toString(),
ImmutableList.of(message1, message1a));
- builder.put(message1.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
+ resultMap.put(message1.get(MessageColumns.ATTACHMENT_LIST_URI).toString(),
ImmutableList.of(createAttachmentDetailsMap(1, "one")));
- Map<String, Object> folderDetailsMap1 = createFolderDetailsMap(1, "one", 0, 0);
- builder.put(folderDetailsMap1.get(FolderColumns.URI).toString(),
+ final Map<String, Object> folderDetailsMap1 =
+ createFolderDetailsMap(1, accountId, "one", 0, 0);
+ resultMap.put(folderDetailsMap1.get(FolderColumns.URI).toString(),
ImmutableList.of(folderDetailsMap1));
- builder.put(accountDetailsMap0.get(AccountColumns.FOLDER_LIST_URI).toString(),
- ImmutableList.of(folderDetailsMap0, folderDetailsMap1));
- builder.put(folderDetailsMap2.get(FolderColumns.URI).toString(),
- ImmutableList.of(folderDetailsMap2));
- Map<String, Object> folderDetailsMap3 = createFolderDetailsMap(3, "three", 0, 0);
- builder.put(folderDetailsMap3.get(FolderColumns.URI).toString(),
- ImmutableList.of(folderDetailsMap3));
- builder.put(accountDetailsMap1.get(AccountColumns.FOLDER_LIST_URI).toString(),
- ImmutableList.of(folderDetailsMap2, folderDetailsMap3));
+ // We currently have two configurations for accounts
+ if (accountId % 2 == 0) {
+ resultMap.put(accountDetailsMap.get(AccountColumns.FOLDER_LIST_URI).toString(),
+ ImmutableList.of(inboxfolderDetailsMap, folderDetailsMap1));
+ } else {
+ resultMap.put(secondFolderDetailsMap.get(FolderColumns.URI).toString(),
+ ImmutableList.of(secondFolderDetailsMap));
+ final Map<String, Object> folderDetailsMap3 =
+ createFolderDetailsMap(3, accountId, "three", 0, 0);
+ resultMap.put(folderDetailsMap3.get(FolderColumns.URI).toString(),
+ ImmutableList.of(folderDetailsMap3));
- builder.put(accountDetailsMap2.get(AccountColumns.FOLDER_LIST_URI).toString(),
- ImmutableList.of(folderDetailsMap0, folderDetailsMap1));
+ resultMap.put(accountDetailsMap.get(AccountColumns.FOLDER_LIST_URI).toString(),
+ ImmutableList.of(secondFolderDetailsMap, folderDetailsMap3));
+ }
- builder.put(accountDetailsMap3.get(AccountColumns.FOLDER_LIST_URI).toString(),
- ImmutableList.of(folderDetailsMap0, folderDetailsMap1));
-
- Map<String, Object> conv3 = createConversationDetailsMap("zeroConv3".hashCode(),
- "zeroConv3", 0, 1, 0);
- builder.put(conv3.get(ConversationColumns.URI).toString(),
+ final Map<String, Object> conv3 =
+ createConversationDetailsMap(accountId, "zeroConv3".hashCode(), "zeroConv3",
+ 0, 1, 0);
+ resultMap.put(conv3.get(ConversationColumns.URI).toString(),
ImmutableList.of(conv3));
- Map<String, Object> conv4 = createConversationDetailsMap("zeroConv4".hashCode(),
- "zeroConv4", 0, 1, 0);
- builder.put(conv4.get(ConversationColumns.URI).toString(),
+ final Map<String, Object> conv4 =
+ createConversationDetailsMap(accountId, "zeroConv4".hashCode(), "zeroConv4",
+ 0, 1, 0);
+ resultMap.put(conv4.get(ConversationColumns.URI).toString(),
ImmutableList.of(conv4));
- builder.put(folderDetailsMap2.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
+ resultMap.put(secondFolderDetailsMap.get(FolderColumns.CONVERSATION_LIST_URI).toString(),
ImmutableList.of(conv3, conv4));
- Map<String, Object> message2 = createMessageDetailsMap("zeroConv3".hashCode(), "zeroConv3",
- 0, true);
- builder.put(message2.get(MessageColumns.URI).toString(), ImmutableList.of(message2));
- builder.put(conv3.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
+ final Map<String, Object> message2 =
+ createMessageDetailsMap(accountId, "zeroConv3".hashCode(), "zeroConv3", 0, true);
+ resultMap.put(message2.get(MessageColumns.URI).toString(), ImmutableList.of(message2));
+ resultMap.put(conv3.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
ImmutableList.of(message2));
- Map<String, Object> message3 = createMessageDetailsMap("zeroConv4".hashCode(), "zeroConv4",
- 0, true);
- builder.put(message3.get(MessageColumns.URI).toString(), ImmutableList.of(message3));
- builder.put(conv4.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
+ final Map<String, Object> message3 =
+ createMessageDetailsMap(accountId, "zeroConv4".hashCode(), "zeroConv4", 0, true);
+ resultMap.put(message3.get(MessageColumns.URI).toString(), ImmutableList.of(message3));
+ resultMap.put(conv4.get(ConversationColumns.MESSAGE_LIST_URI).toString(),
ImmutableList.of(message3));
- MOCK_QUERY_RESULTS = builder.build();
+ // Add the account to the list of accounts
+ List<Map<String, Object>> accountList = resultMap.get(getAccountsUri().toString());
+ if (accountList == null) {
+ accountList = Lists.newArrayList();
+ resultMap.put(getAccountsUri().toString(), accountList);
+ }
+ accountList.add(accountDetailsMap);
}
- private static Map<String, Object> createConversationDetailsMap(int conversationId,
- String subject, int hasAttachments, int messageCount, int draftCount) {
- final String conversationUri = "content://" + AUTHORITY + "/conversation/" + conversationId;
+ public static void initializeMockProvider() {
+ MOCK_QUERY_RESULTS = Maps.newHashMap();
+
+ for (int accountId = 0; accountId < NUM_ACCOUNTS; accountId++) {
+ initializeAccount(accountId, MOCK_QUERY_RESULTS);
+ }
+ }
+
+ private static Map<String, Object> createConversationDetailsMap(int accountId,
+ int conversationId, String subject, int hasAttachments, int messageCount,
+ int draftCount) {
+ final String conversationUri = getMockConversationUri(accountId, conversationId);
Map<String, Object> conversationMap = Maps.newHashMap();
conversationMap.put(BaseColumns._ID, Long.valueOf(conversationId));
conversationMap.put(ConversationColumns.URI, conversationUri);
@@ -237,10 +218,11 @@
}
folders.add(folder);
-
}
final FolderList folderList = FolderList.copyOf(folders);
- conversationMap.put(ConversationColumns.RAW_FOLDERS, folderList);
+ conversationMap.put(
+ MockRespondMatrixCursor.MOCK_RESPOND_PREFIX +
+ ConversationCursorCommand.COMMAND_GET_RAW_FOLDERS, folderList);
return conversationMap;
}
@@ -262,9 +244,10 @@
return info.toBlob();
}
- private static Map<String, Object> createMessageDetailsMap(int messageId, String subject,
- int hasAttachments, boolean addReplyTo) {
- final String messageUri = "content://" + AUTHORITY + "/message/" + messageId;
+ private static Map<String, Object> createMessageDetailsMap(int accountId, int messageId,
+ String subject, int hasAttachments, boolean addReplyTo) {
+ final String accountUri = getMockAccountUri(accountId);
+ final String messageUri = getMockMessageUri(accountId, messageId);
Map<String, Object> messageMap = Maps.newHashMap();
messageMap.put(BaseColumns._ID, Long.valueOf(messageId));
messageMap.put(MessageColumns.URI, messageUri);
@@ -278,6 +261,7 @@
messageMap.put(MessageColumns.ATTACHMENT_LIST_URI, messageUri + "/getAttachments");
messageMap.put(MessageColumns.TO, "account1@mock.com, account2@mock.com");
messageMap.put(MessageColumns.FROM, "fromaccount1@mock.com");
+ messageMap.put(MessageColumns.MESSAGE_ACCOUNT_URI, accountUri);
return messageMap;
}
@@ -290,14 +274,15 @@
return attachmentMap;
}
- private static Map<String, Object> createFolderDetailsMap(int folderId, String name,
- int unread, int total) {
- return createFolderDetailsMap(folderId, name, false, unread, total);
+ private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId,
+ String name, int unread, int total) {
+ return createFolderDetailsMap(folderId, accountId, name, false, unread, total);
}
- private static Map<String, Object> createFolderDetailsMap(int folderId, String name,
- boolean hasChildren, int unread, int total) {
- final String folderUri = "content://" + AUTHORITY + "/folder/" + folderId;
+ private static Map<String, Object> createFolderDetailsMap(int folderId, int accountId,
+ String name, boolean hasChildren, int unread, int total) {
+ final String folderUri = getMockAccountFolderUri(accountId, folderId);
+
Map<String, Object> folderMap = Maps.newHashMap();
folderMap.put(BaseColumns._ID, Long.valueOf(folderId));
folderMap.put(FolderColumns.URI, folderUri);
@@ -319,12 +304,12 @@
}
// Temporarily made this public to allow the Gmail accounts to use the mock ui provider uris
- public static Map<String, Object> createAccountDetailsMap(int accountId, boolean cacheMap,
- String defaultInbox) {
+ public static Map<String, Object> createAccountDetailsMap(int accountId,String defaultInbox) {
final String accountUri = getMockAccountUri(accountId);
Map<String, Object> accountMap = Maps.newHashMap();
accountMap.put(BaseColumns._ID, Long.valueOf(accountId));
accountMap.put(AccountColumns.NAME, "account" + accountId + "@mockuiprovider.com");
+ accountMap.put(AccountColumns.TYPE, "com.android.mail.providers.protos.mock");
accountMap.put(AccountColumns.PROVIDER_VERSION, Long.valueOf(1));
accountMap.put(AccountColumns.URI, Uri.parse(accountUri));
accountMap.put(AccountColumns.CAPABILITIES,
@@ -353,12 +338,15 @@
}
accountMap.put(AccountColumns.ACCOUNT_FROM_ADDRESSES, replyFroms.toString());
accountMap.put(AccountColumns.FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
+ accountMap.put(AccountColumns.FULL_FOLDER_LIST_URI, Uri.parse(accountUri + "/folders"));
accountMap.put(AccountColumns.SEARCH_URI, Uri.parse(accountUri + "/search"));
accountMap.put(AccountColumns.EXPUNGE_MESSAGE_URI,
Uri.parse(accountUri + "/expungeMessage"));
accountMap.put(AccountColumns.UNDO_URI, Uri.parse(accountUri + "/undo"));
accountMap.put(AccountColumns.SETTINGS_INTENT_URI, Uri.EMPTY);
accountMap.put(AccountColumns.HELP_INTENT_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.SEND_FEEDBACK_INTENT_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.REAUTHENTICATION_INTENT_URI, Uri.EMPTY);
accountMap.put(AccountColumns.SYNC_STATUS, 0);
accountMap.put(AccountColumns.COMPOSE_URI, Uri.parse(accountUri + "/compose"));
accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI,
@@ -366,18 +354,34 @@
accountMap.put(AccountColumns.MIME_TYPE, "account/mock");
accountMap.put(AccountColumns.COLOR, 0);
accountMap.put(AccountColumns.RECENT_FOLDER_LIST_URI, Uri.EMPTY);
- accountMap.put(AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI,
- Uri.EMPTY);
- accountMap.put(AccountColumns.MANUAL_SYNC_URI,
- Uri.EMPTY);
- accountMap.put(AccountColumns.VIEW_INTENT_PROXY_URI,
- Uri.EMPTY);
+ accountMap.put(AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.MANUAL_SYNC_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.VIEW_INTENT_PROXY_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.ACCOUNT_COOKIE_QUERY_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.UPDATE_SETTINGS_URI, Uri.EMPTY);
+ accountMap.put(AccountColumns.ENABLE_MESSAGE_TRANSFORMS, 1);
- // TODO: store the default inbox
+
+ // Add settings columns
+ accountMap.put(SettingsColumns.SIGNATURE, "");
+ accountMap.put(SettingsColumns.AUTO_ADVANCE, 1);
+ accountMap.put(SettingsColumns.MESSAGE_TEXT_SIZE, 1);
+ accountMap.put(SettingsColumns.SNAP_HEADERS, 1);
+ accountMap.put(SettingsColumns.REPLY_BEHAVIOR, 1);
+ accountMap.put(SettingsColumns.CONV_LIST_ICON, 1);
+ accountMap.put(SettingsColumns.CONFIRM_DELETE, 1);
+ accountMap.put(SettingsColumns.CONFIRM_ARCHIVE, 1);
+ accountMap.put(SettingsColumns.CONFIRM_SEND, 1);
accountMap.put(SettingsColumns.DEFAULT_INBOX, defaultInbox);
- if (cacheMap) {
- addAccountInfoToAccountCache(accountMap);
- }
+ accountMap.put(SettingsColumns.DEFAULT_INBOX_NAME, "Inbox");
+ accountMap.put(SettingsColumns.FORCE_REPLY_FROM_DEFAULT, 1);
+ accountMap.put(SettingsColumns.MAX_ATTACHMENT_SIZE, 25 * 1024 * 1024);
+ accountMap.put(SettingsColumns.SWIPE, 1);
+ accountMap.put(SettingsColumns.PRIORITY_ARROWS_ENABLED, 1);
+ accountMap.put(SettingsColumns.SETUP_INTENT_URI, Uri.EMPTY);
+ accountMap.put(SettingsColumns.CONVERSATION_VIEW_MODE, 1);
+ accountMap.put(SettingsColumns.VEILED_ADDRESS_PATTERN, null);
+ accountMap.put(SettingsColumns.MOVE_TO_INBOX, Uri.EMPTY);
return accountMap;
}
@@ -385,6 +389,18 @@
return "content://" + AUTHORITY + "/account/" + accountId;
}
+ private static String getMockAccountFolderUri(int accountId, int folderId) {
+ return getMockAccountUri(accountId) + "/folder/" + folderId;
+ }
+
+ private static String getMockConversationUri(int accountId, int conversationId) {
+ return getMockAccountUri(accountId) + "/conversation/" + conversationId;
+ }
+
+ private static String getMockMessageUri(int accountId, int messageId) {
+ return getMockAccountUri(accountId) + "/message/" + messageId;
+ }
+
@Override
public boolean onCreate() {
MockUiProvider.initializeMockProvider();
@@ -395,10 +411,7 @@
public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
- // TODO (pwestbro): respect the projection that is specified by the caller
-
- final List<Map<String, Object>> queryResults =
- MOCK_QUERY_RESULTS.get(url.toString());
+ final List<Map<String, Object>> queryResults = MOCK_QUERY_RESULTS.get(url.toString());
if (queryResults != null && queryResults.size() > 0) {
// Get the projection. If there are rows in the result set, pick the first item to
@@ -408,8 +421,8 @@
Set<String> keys = queryResults.get(0).keySet();
projection = keys.toArray(new String[keys.size()]);
}
- MatrixCursor matrixCursor =
- new MatrixCursorWithCachedColumns(projection, queryResults.size());
+ final MatrixCursor matrixCursor =
+ new MockRespondMatrixCursor(projection, queryResults.size(), queryResults);
for (Map<String, Object> queryResult : queryResults) {
MatrixCursor.RowBuilder rowBuilder = matrixCursor.newRow();
@@ -447,61 +460,7 @@
@VisibleForTesting
static Uri getAccountsUri() {
- // TODO: this should probably return a different specific to the mock account list
- return Uri.parse(BASE_URI_STRING + "/");
- }
-
- private static void addAccountInfoToAccountCache(Map<String, Object> accountInfo) {
- final Parcel dest = Parcel.obtain();
- dest.writeString((String) accountInfo.get(AccountColumns.NAME));
- dest.writeString("mock");
-
- final int providerVersion = 1;
- dest.writeInt(providerVersion);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.URI), 0);
- dest.writeInt((Integer) accountInfo.get(AccountColumns.CAPABILITIES));
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.FOLDER_LIST_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.FULL_FOLDER_LIST_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEARCH_URI), 0);
- dest.writeString((String) accountInfo.get(AccountColumns.ACCOUNT_FROM_ADDRESSES));
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.EXPUNGE_MESSAGE_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.UNDO_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SETTINGS_INTENT_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.HELP_INTENT_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.SEND_FEEDBACK_INTENT_URI), 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.REAUTHENTICATION_INTENT_URI), 0);
- dest.writeInt((Integer) accountInfo.get(AccountColumns.SYNC_STATUS));
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.COMPOSE_URI), 0);
- dest.writeString((String) accountInfo.get(AccountColumns.MIME_TYPE));
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.RECENT_FOLDER_LIST_URI), 0);
- dest.writeInt((Integer) accountInfo.get(AccountColumns.COLOR));
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.DEFAULT_RECENT_FOLDER_LIST_URI),
- 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.MANUAL_SYNC_URI),
- 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.VIEW_INTENT_PROXY_URI),
- 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.ACCOUNT_COOKIE_QUERY_URI),
- 0);
- dest.writeParcelable((Uri) accountInfo.get(AccountColumns.UPDATE_SETTINGS_URI),
- 0);
- Parcel p = Parcel.obtain();
- p.writeString("");
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeInt(1);
- p.writeString((String)accountInfo.get(SettingsColumns.DEFAULT_INBOX));
- p.writeInt(1);
- p.setDataPosition(0);
- dest.writeString(new Settings(p).serialize());
- dest.setDataPosition(0);
- final Account account = new Account(dest);
- MailAppProvider.addAccount(account, MOCK_ACCOUNTS_URI);
+ return MOCK_ACCOUNTS_URI;
}
}
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index fe12594..6aec68c 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -99,7 +99,6 @@
import com.android.mail.utils.Observable;
import com.android.mail.utils.Utils;
import com.android.mail.utils.VeiledAddressMatcher;
-
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
@@ -941,7 +940,7 @@
}
// If the previous folder was null, or if the two folders represent different data, then we
// consider that the folder has changed.
- if (mFolder == null || !newFolder.uri.equals(mFolder.uri)) {
+ if (mFolder == null || !newFolder.equals(mFolder)) {
mFolderChanged = true;
}
}
@@ -1185,8 +1184,11 @@
mRecentFolderList.initialize(mActivity);
mVeiledMatcher.initialize(this);
+ // the "open drawer description" argument is for when the drawer is open
+ // so tell the user that interacting will cause the drawer to close
+ // and vice versa for the "close drawer description" argument
mDrawerToggle = new ActionBarDrawerToggle((Activity) mActivity, mDrawerContainer,
- R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close);
+ R.drawable.ic_drawer, R.string.drawer_close, R.string.drawer_open);
mDrawerListener = new MailDrawerListener();
mDrawerContainer.setDrawerListener(mDrawerListener);
mDrawerContainer.setDrawerShadow(
@@ -2120,8 +2122,7 @@
// If search list/conv mode: disable indicator
// Indicator is enabled either in conversation list or folder list mode.
return isDrawerEnabled() && !ViewMode.isSearchMode(viewMode)
- && (viewMode == ViewMode.FOLDER_LIST
- || (viewMode == ViewMode.CONVERSATION_LIST && isTopLevel));
+ && (viewMode == ViewMode.CONVERSATION_LIST && isTopLevel);
}
/**
@@ -2282,7 +2283,7 @@
} else if (intent.hasExtra(Utils.EXTRA_FOLDER)) {
final Folder folder =
Folder.fromString(intent.getStringExtra(Utils.EXTRA_FOLDER));
- folderUri = folder.uri;
+ folderUri = folder.folderUri.fullUri;
} else {
final Bundle extras = intent.getExtras();
LogUtils.d(LOG_TAG, "Couldn't find a folder URI in the extras: %s",
@@ -3125,7 +3126,7 @@
(UIProvider.FolderCapabilities.CAN_ACCEPT_MOVED_MESSAGES)
&& folder.supportsCapability
(UIProvider.FolderCapabilities.CAN_HOLD_MAIL)
- && !mFolder.uri.equals(folder.uri));
+ && !mFolder.equals(folder));
}
/**
@@ -3184,11 +3185,11 @@
for (Conversation target : conversations) {
folderUris = new ArrayList<Uri>();
adds = new ArrayList<Boolean>();
- folderUris.add(folder.uri);
+ folderUris.add(folder.folderUri.fullUri);
adds.add(Boolean.TRUE);
final HashMap<Uri, Folder> targetFolders =
Folder.hashMapForFolders(target.getRawFolders());
- targetFolders.put(folder.uri, folder);
+ targetFolders.put(folder.folderUri.fullUri, folder);
ops.add(mConversationListCursor.getConversationFolderOperation(target,
folderUris, adds, targetFolders.values()));
}
@@ -3240,14 +3241,14 @@
for (Conversation target : mConversations) {
folderUris = new ArrayList<Uri>();
adds = new ArrayList<Boolean>();
- folderUris.add(mStarred.uri);
+ folderUris.add(mStarred.folderUri.fullUri);
adds.add(Boolean.TRUE);
- folderUris.add(mInitialFolder.uri);
+ folderUris.add(mInitialFolder.folderUri.fullUri);
adds.add(Boolean.FALSE);
final HashMap<Uri, Folder> targetFolders =
Folder.hashMapForFolders(target.getRawFolders());
- targetFolders.put(mStarred.uri, mStarred);
- targetFolders.remove(mInitialFolder.uri);
+ targetFolders.put(mStarred.folderUri.fullUri, mStarred);
+ targetFolders.remove(mInitialFolder.folderUri.fullUri);
values.put(ConversationColumns.STARRED, true);
operation = mConversationListCursor.getConversationFolderOperation(target,
folderUris, adds, targetFolders.values(), values);
@@ -3371,7 +3372,7 @@
LogUtils.d(LOG_TAG, "LOADER_FOLDER_CURSOR created");
final ObjectCursorLoader<Folder> loader = new
ObjectCursorLoader<Folder>(
- mContext, mFolder.uri, everything, Folder.FACTORY);
+ mContext, mFolder.folderUri.fullUri, everything, Folder.FACTORY);
loader.setUpdateThrottle(mFolderItemUpdateDelayMs);
return loader;
case LOADER_RECENT_FOLDERS:
@@ -3750,12 +3751,12 @@
target.localDeleteOnUpdate = true;
}
for (FolderOperation op : mFolderOps) {
- folderUris.add(op.mFolder.uri);
+ folderUris.add(op.mFolder.folderUri.fullUri);
adds.add(op.mAdd ? Boolean.TRUE : Boolean.FALSE);
if (op.mAdd) {
- targetFolders.put(op.mFolder.uri, op.mFolder);
+ targetFolders.put(op.mFolder.folderUri.fullUri, op.mFolder);
} else {
- targetFolders.remove(op.mFolder.uri);
+ targetFolders.remove(op.mFolder.folderUri.fullUri);
}
}
ops.add(mConversationListCursor.getConversationFolderOperation(target,
diff --git a/src/com/android/mail/ui/AbstractConversationWebViewClient.java b/src/com/android/mail/ui/AbstractConversationWebViewClient.java
index 0684b0c..dc59bce 100644
--- a/src/com/android/mail/ui/AbstractConversationWebViewClient.java
+++ b/src/com/android/mail/ui/AbstractConversationWebViewClient.java
@@ -67,11 +67,15 @@
boolean result = false;
final Intent intent;
- Uri uri = Uri.parse(url);
+ final Uri uri = Uri.parse(url);
if (mAccount != null && !Utils.isEmpty(mAccount.viewIntentProxyUri)) {
intent = generateProxyIntent(uri);
} else {
intent = new Intent(Intent.ACTION_VIEW, uri);
+
+ // If this is a mailto: uri, we want to set the account name in the intent so
+ // the ComposeActivity can default to the current account
+ Utils.addAccountToMailtoIntent(intent, mAccount);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, mActivity.getPackageName());
}
diff --git a/src/com/android/mail/ui/AnimatedAdapter.java b/src/com/android/mail/ui/AnimatedAdapter.java
index cdf9919..a8a995e 100644
--- a/src/com/android/mail/ui/AnimatedAdapter.java
+++ b/src/com/android/mail/ui/AnimatedAdapter.java
@@ -52,6 +52,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -86,6 +87,33 @@
private final Handler mHandler;
protected long mLastLeaveBehind = -1;
+ public interface ConversationListListener {
+ /**
+ * View the message at the given position.
+ *
+ * @param position The position of the conversation in the list (as opposed to its position
+ * in the cursor)
+ */
+ void viewConversation(int position);
+
+ /**
+ * @return <code>true</code> if the list is in selection mode, <code>false</code> otherwise
+ */
+ boolean isInSelectionMode();
+
+ /**
+ * @return <code>true</code> if the list is just entering selection mode (so animations may
+ * be required), <code>false</code> otherwise
+ */
+ boolean isEnteringSelectionMode();
+
+ /**
+ * @return <code>true</code> if the list is just exiting selection mode (so animations may
+ * be required), <code>false</code> otherwise
+ */
+ boolean isExitingSelectionMode();
+ }
+
private final AnimatorListener mAnimatorListener = new AnimatorListenerAdapter() {
@Override
@@ -166,6 +194,7 @@
/** True if priority inbox markers are enabled, false otherwise. */
private boolean mPriorityMarkersEnabled;
private final ControllableActivity mActivity;
+ private final ConversationListListener mConversationListListener;
private final AccountObserver mAccountListener = new AccountObserver() {
@Override
public void onChanged(Account newAccount) {
@@ -193,6 +222,9 @@
/** List of all child folders for this folder. */
private List<NestedFolderView> mFolderViews;
+ private final SparseArray<WeakReference<ConversationSetObserver>> mItemViewSetObservers =
+ new SparseArray<WeakReference<ConversationSetObserver>>();
+
private void setAccount(Account newAccount) {
mAccount = newAccount;
mPriorityMarkersEnabled = mAccount.settings.priorityArrowsEnabled;
@@ -204,13 +236,15 @@
public AnimatedAdapter(Context context, ConversationCursor cursor,
ConversationSelectionSet batch, ControllableActivity activity,
- SwipeableListView listView, final List<ConversationSpecialItemView> specialViews,
+ final ConversationListListener conversationListListener, SwipeableListView listView,
+ final List<ConversationSpecialItemView> specialViews,
final ObjectCursor<Folder> childFolders) {
super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0);
mContext = context;
mBatchConversations = batch;
setAccount(mAccountListener.initialize(activity.getAccountController()));
mActivity = activity;
+ mConversationListListener = conversationListListener;
mShowFooter = false;
mListView = listView;
mFolderViews = getNestedFolders(childFolders);
@@ -349,12 +383,12 @@
}
public View createConversationItemView(SwipeableConversationItemView view, Context context,
- Conversation conv) {
+ Conversation conv, final int position) {
if (view == null) {
view = new SwipeableConversationItemView(context, mAccount.name);
}
- view.bind(conv, mActivity, mBatchConversations, mFolder, getCheckboxSetting(),
- mSwipeEnabled, mPriorityMarkersEnabled, this);
+ view.bind(conv, mActivity, mConversationListListener, mBatchConversations, mFolder,
+ getCheckboxSetting(), mSwipeEnabled, mPriorityMarkersEnabled, this, position);
return view;
}
@@ -515,7 +549,7 @@
((SwipeableConversationItemView) convertView).reset();
}
final View v = createConversationItemView((SwipeableConversationItemView) convertView,
- mContext, conv);
+ mContext, conv, position);
Utils.traceEndSection();
return v;
}
@@ -730,8 +764,8 @@
SwipeableConversationItemView view = (SwipeableConversationItemView) super.getView(
position, null, parent);
view.reset();
- view.bind(conversation, mActivity, mBatchConversations, mFolder, getCheckboxSetting(),
- mSwipeEnabled, mPriorityMarkersEnabled, this);
+ view.bind(conversation, mActivity, mConversationListListener, mBatchConversations, mFolder,
+ getCheckboxSetting(), mSwipeEnabled, mPriorityMarkersEnabled, this, position);
mAnimatingViews.put(conversation.id, view);
return view;
}
@@ -1053,4 +1087,85 @@
specialView.onCabModeEntered();
}
}
+
+ private final ConversationSetObserver mConversationSetObserver = new ConversationSetObserver() {
+ @Override
+ public void onSetPopulated(final ConversationSelectionSet set) {
+ pruneEntries();
+
+ for (int i = 0; i < mItemViewSetObservers.size(); i++) {
+ final WeakReference<ConversationSetObserver> ref = mItemViewSetObservers.valueAt(i);
+ final ConversationSetObserver observer = ref.get();
+
+ if (observer == null) {
+ LogUtils.wtf(LOG_TAG, "ConversationSetObserver null after pruneEntries()");
+ } else {
+ observer.onSetPopulated(set);
+ }
+ }
+ }
+
+ @Override
+ public void onSetEmpty() {
+ pruneEntries();
+
+ for (int i = 0; i < mItemViewSetObservers.size(); i++) {
+ final WeakReference<ConversationSetObserver> ref = mItemViewSetObservers.valueAt(i);
+ final ConversationSetObserver observer = ref.get();
+
+ if (observer == null) {
+ LogUtils.wtf(LOG_TAG, "ConversationSetObserver null after pruneEntries()");
+ } else {
+ observer.onSetEmpty();
+ }
+ }
+ }
+
+ @Override
+ public void onSetChanged(final ConversationSelectionSet set) {
+ pruneEntries();
+
+ for (int i = 0; i < mItemViewSetObservers.size(); i++) {
+ final WeakReference<ConversationSetObserver> ref = mItemViewSetObservers.valueAt(i);
+ final ConversationSetObserver observer = ref.get();
+
+ if (observer == null) {
+ LogUtils.wtf(LOG_TAG, "ConversationSetObserver null after pruneEntries()");
+ } else {
+ observer.onSetChanged(set);
+ }
+ }
+ }
+
+ private void pruneEntries() {
+ final int[] deadKeys = new int[mItemViewSetObservers.size()];
+ int deadKeyIndex = 0;
+
+ for (int i = 0; i < mItemViewSetObservers.size(); i++) {
+ final WeakReference<ConversationSetObserver> ref = mItemViewSetObservers.valueAt(i);
+ final ConversationSetObserver observer = ref.get();
+
+ if (observer == null) {
+ deadKeys[deadKeyIndex++] = mItemViewSetObservers.keyAt(i);
+ }
+ }
+
+ for (int i = deadKeyIndex - 1; i >= 0; i--) {
+ mItemViewSetObservers.delete(deadKeys[i]);
+ }
+ }
+ };
+
+ public ConversationSetObserver getConversationSetObserver() {
+ return mConversationSetObserver;
+ }
+
+ public void registerConversationSetObserver(final ConversationSetObserver observer) {
+ mItemViewSetObservers.put(observer.hashCode(),
+ new WeakReference<ConversationSetObserver>(observer));
+ }
+
+ public void unregisterConversationSetObserver(final ConversationSetObserver observer) {
+ mItemViewSetObservers.delete(observer.hashCode());
+ }
}
diff --git a/src/com/android/mail/ui/ConversationListFragment.java b/src/com/android/mail/ui/ConversationListFragment.java
index ddb52d7..34f7625 100644
--- a/src/com/android/mail/ui/ConversationListFragment.java
+++ b/src/com/android/mail/ui/ConversationListFragment.java
@@ -56,10 +56,10 @@
import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AccountCapabilities;
-import com.android.mail.providers.UIProvider.ConversationListIcon;
import com.android.mail.providers.UIProvider.FolderCapabilities;
import com.android.mail.providers.UIProvider.FolderType;
import com.android.mail.providers.UIProvider.Swipe;
+import com.android.mail.ui.AnimatedAdapter.ConversationListListener;
import com.android.mail.ui.SwipeableListView.ListItemSwipedListener;
import com.android.mail.ui.SwipeableListView.ListItemsRemovedListener;
import com.android.mail.ui.ViewMode.ModeChangeListener;
@@ -148,6 +148,13 @@
/** Hash of the Conversation Cursor we last obtained from the controller. */
private int mConversationCursorHash;
+ /** Duration, in milliseconds, of the CAB mode (peek icon) animation. */
+ private static long sSelectionModeAnimationDuration = -1;
+ /** The time at which we last entered CAB mode. */
+ private long mSelectionModeEnteredTimestamp = -1;
+ /** The time at which we last exited CAB mode. */
+ private long mSelectionModeExitedTimestamp = -1;
+
/**
* If the current list is for a folder with children, this set of loader callbacks will
* create a loader for all the child folders, and will return an {@link ObjectCursor} over the
@@ -284,6 +291,12 @@
@Override
public void onActivityCreated(Bundle savedState) {
super.onActivityCreated(savedState);
+
+ if (sSelectionModeAnimationDuration < 0) {
+ sSelectionModeAnimationDuration = getResources().getInteger(
+ R.integer.conv_item_view_cab_anim_duration);
+ }
+
// Strictly speaking, we get back an android.app.Activity from
// getActivity. However, the
// only activity creating a ConversationListContext is a MailActivity
@@ -336,7 +349,8 @@
}
mListAdapter = new AnimatedAdapter(mActivity.getApplicationContext(), conversationCursor,
- mActivity.getSelectedSet(), mActivity, mListView, specialItemViews, null);
+ mActivity.getSelectedSet(), mActivity, mConversationListListener, mListView,
+ specialItemViews, null);
mListAdapter.addFooter(mFooterView);
mListView.setAdapter(mListAdapter);
mSelectedSet = mActivity.getSelectedSet();
@@ -568,7 +582,7 @@
* <pre>
* | Checkboxes | No Checkboxes
* ----------+------------+---------------
- * CAB mode | Peek | Select
+ * CAB mode | Select | Select
* List mode | Peek | Peek
* </pre>
*
@@ -582,12 +596,10 @@
final FolderSelector selector = mActivity.getFolderSelector();
selector.onFolderSelected(((NestedFolderView) view).getFolder());
} else if (view instanceof ToggleableItem) {
- final boolean showSenderImage =
- (mAccount.settings.convListIcon == ConversationListIcon.SENDER_IMAGE);
- if (!showSenderImage && !mSelectedSet.isEmpty()) {
+ if (!mSelectedSet.isEmpty()) {
((ToggleableItem) view).toggleSelectedState();
} else {
- viewConversation(position);
+ mConversationListListener.viewConversation(position);
}
} else {
// Ignore anything that is not a conversation item. Could be a footer.
@@ -609,11 +621,15 @@
if (conversationCursor != null) {
conversationCursor.handleNotificationActions();
}
+
+ mSelectedSet.addObserver(mConversationSetObserver);
}
@Override
public void onPause() {
super.onPause();
+
+ mSelectedSet.removeObserver(mConversationSetObserver);
}
@Override
@@ -674,34 +690,49 @@
onConversationListStatusUpdated();
}
- /**
- * View the message at the given position.
- *
- * @param position The position of the conversation in the list (as opposed to its position in
- * the cursor)
- */
- protected void viewConversation(final int position) {
- LogUtils.d(LOG_TAG, "ConversationListFragment.viewConversation(%d)", position);
+ private final ConversationListListener mConversationListListener =
+ new ConversationListListener() {
+ @Override
+ public void viewConversation(final int position) {
+ LogUtils.d(LOG_TAG, "ConversationListFragment.viewConversation(%d)", position);
- final ConversationCursor cursor =
- (ConversationCursor) getAnimatedAdapter().getItem(position);
+ final ConversationCursor cursor =
+ (ConversationCursor) getAnimatedAdapter().getItem(position);
- if (cursor == null) {
- LogUtils.e(LOG_TAG,
- "unable to open conv at cursor pos=%s cursor=%s getPositionOffset=%s",
- position, cursor, getAnimatedAdapter().getPositionOffset(position));
- return;
+ if (cursor == null) {
+ LogUtils.e(LOG_TAG,
+ "unable to open conv at cursor pos=%s cursor=%s getPositionOffset=%s",
+ position, cursor, getAnimatedAdapter().getPositionOffset(position));
+ return;
+ }
+
+ final Conversation conv = cursor.getConversation();
+ /*
+ * The cursor position may be different than the position method parameter because of
+ * special views in the list.
+ */
+ conv.position = cursor.getPosition();
+ setSelected(conv.position, true);
+ mCallbacks.onConversationSelected(conv, false /* inLoaderCallbacks */);
}
- final Conversation conv = cursor.getConversation();
- /*
- * The cursor position may be different than the position method parameter because of
- * special views in the list.
- */
- conv.position = cursor.getPosition();
- setSelected(conv.position, true);
- mCallbacks.onConversationSelected(conv, false /* inLoaderCallbacks */);
- }
+ @Override
+ public boolean isInSelectionMode() {
+ return !mSelectedSet.isEmpty();
+ }
+
+ @Override
+ public boolean isEnteringSelectionMode() {
+ return System.currentTimeMillis() <
+ (mSelectionModeEnteredTimestamp + sSelectionModeAnimationDuration);
+ }
+
+ @Override
+ public boolean isExitingSelectionMode() {
+ return System.currentTimeMillis() <
+ (mSelectionModeExitedTimestamp + sSelectionModeAnimationDuration);
+ }
+ };
/**
* Sets the selected conversation to the position given here.
@@ -950,4 +981,25 @@
public void clear() {
mListView.setAdapter(null);
}
+
+ private final ConversationSetObserver mConversationSetObserver = new ConversationSetObserver() {
+ @Override
+ public void onSetPopulated(final ConversationSelectionSet set) {
+ mSelectionModeEnteredTimestamp = System.currentTimeMillis();
+
+ mListAdapter.getConversationSetObserver().onSetPopulated(set);
+ }
+
+ @Override
+ public void onSetEmpty() {
+ mSelectionModeExitedTimestamp = System.currentTimeMillis();
+
+ mListAdapter.getConversationSetObserver().onSetEmpty();
+ }
+
+ @Override
+ public void onSetChanged(final ConversationSelectionSet set) {
+ mListAdapter.getConversationSetObserver().onSetChanged(set);
+ }
+ };
}
diff --git a/src/com/android/mail/ui/ConversationListHelper.java b/src/com/android/mail/ui/ConversationListHelper.java
index f7a6862..dec28a3 100644
--- a/src/com/android/mail/ui/ConversationListHelper.java
+++ b/src/com/android/mail/ui/ConversationListHelper.java
@@ -19,9 +19,12 @@
import com.google.common.collect.Lists;
import android.content.Context;
+import android.view.LayoutInflater;
import com.android.mail.providers.Account;
+import com.android.mail.R;
+
import java.util.ArrayList;
public class ConversationListHelper {
@@ -30,8 +33,14 @@
*/
public ArrayList<ConversationSpecialItemView> makeConversationListSpecialViews(Context context,
Account account, FolderSelector listener) {
- // TODO: Move conversation photo teaser view here once
- // getConversationListIcon() is moved out of Persistence
- return Lists.newArrayList();
+ // Conversation photo teaser view
+ final ConversationPhotoTeaserView conversationPhotoTeaser =
+ (ConversationPhotoTeaserView) LayoutInflater.from(context)
+ .inflate(R.layout.conversation_photo_teaser_view, null);
+
+
+ final ArrayList<ConversationSpecialItemView> itemViews = Lists.newArrayList();
+ itemViews.add(conversationPhotoTeaser);
+ return itemViews;
}
}
diff --git a/src/com/android/mail/ui/ConversationListView.java b/src/com/android/mail/ui/ConversationListView.java
index fcfce47..25ac4a6 100644
--- a/src/com/android/mail/ui/ConversationListView.java
+++ b/src/com/android/mail/ui/ConversationListView.java
@@ -416,7 +416,7 @@
attr.recycle();
} else {
// Default color
- setBackgroundColor(R.color.list_background_color);
+ setBackgroundColor(getResources().getColor(R.color.list_background_color));
}
}
diff --git a/src/com/android/mail/ui/ConversationPhotoTeaserView.java b/src/com/android/mail/ui/ConversationPhotoTeaserView.java
index 0b21883..8665c9e 100644
--- a/src/com/android/mail/ui/ConversationPhotoTeaserView.java
+++ b/src/com/android/mail/ui/ConversationPhotoTeaserView.java
@@ -167,7 +167,7 @@
}
protected boolean shouldShowSenderImage() {
- return false;
+ return mMailPrefs.getShowSenderImages();
}
@Override
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index 74ac38a..80eb4e3 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -85,7 +85,7 @@
/**
* The conversation view UI component.
*/
-public final class ConversationViewFragment extends AbstractConversationViewFragment implements
+public class ConversationViewFragment extends AbstractConversationViewFragment implements
SuperCollapsedBlock.OnClickListener, OnLayoutChangeListener,
MessageHeaderView.MessageHeaderViewCallbacks {
@@ -118,9 +118,9 @@
*/
private final int LOAD_WAIT_UNTIL_VISIBLE = 2;
- private ConversationContainer mConversationContainer;
+ protected ConversationContainer mConversationContainer;
- private ConversationWebView mWebView;
+ protected ConversationWebView mWebView;
private ScrollIndicatorsView mScrollIndicators;
@@ -128,11 +128,11 @@
private View mNewMessageBar;
- private HtmlConversationTemplates mTemplates;
+ protected HtmlConversationTemplates mTemplates;
private final MailJsBridge mJsBridge = new MailJsBridge();
- private ConversationViewAdapter mAdapter;
+ protected ConversationViewAdapter mAdapter;
private boolean mViewsCreated;
// True if we attempted to render before the views were laid out
@@ -149,7 +149,7 @@
private int mMaxAutoLoadMessages;
- private int mSideMarginPx;
+ protected int mSideMarginPx;
/**
* If this conversation fragment is not visible, and it's inappropriate to load up front,
@@ -359,9 +359,11 @@
// content is loaded and ready to draw, since WebView delays firing this event until the
// layers are composited and everything is ready to draw.
// This signal does not seem to be reliable, so just use the old method for now.
- mEnableContentReadySignal = Utils.isRunningJellybeanOrLater();
- mWebView.setUseSoftwareLayer(!mEnableContentReadySignal);
- mWebView.onUserVisibilityChanged(isUserVisible());
+ final boolean isJBOrLater = Utils.isRunningJellybeanOrLater();
+ final boolean isUserVisible = isUserVisible();
+ mWebView.setUseSoftwareLayer(!isJBOrLater);
+ mEnableContentReadySignal = isJBOrLater && isUserVisible;
+ mWebView.onUserVisibilityChanged(isUserVisible);
mWebView.setWebViewClient(mWebViewClient);
final WebChromeClient wcc = new WebChromeClient() {
@Override
@@ -390,6 +392,22 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ if (mWebView != null) {
+ mWebView.onResume();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mWebView != null) {
+ mWebView.onPause();
+ }
+ }
+
+ @Override
public void onDestroyView() {
super.onDestroyView();
mConversationContainer.setOverlayAdapter(null);
@@ -578,7 +596,7 @@
* conversation header), and return an HTML document with spacer divs inserted for all overlays.
*
*/
- private String renderMessageBodies(MessageCursor messageCursor,
+ protected String renderMessageBodies(MessageCursor messageCursor,
boolean enableContentReadySignal) {
int pos = -1;
@@ -763,7 +781,7 @@
return mTemplates.emit();
}
- private int measureOverlayHeight(int position) {
+ protected int measureOverlayHeight(int position) {
return measureOverlayHeight(mAdapter.getItem(position));
}
@@ -920,7 +938,7 @@
return positions;
}
- private Address getAddress(String rawFrom) {
+ protected Address getAddress(String rawFrom) {
Address addr;
synchronized (mAddressCache) {
addr = mAddressCache.get(rawFrom);
@@ -949,7 +967,7 @@
mWebView.setContentSizeChangeListener(mWebViewSizeChangeListener);
}
- private static boolean isOverviewMode(Account acct) {
+ public static boolean isOverviewMode(Account acct) {
return acct.settings.isOverviewMode();
}
@@ -1466,5 +1484,4 @@
}
}
-
}
diff --git a/src/com/android/mail/ui/ConversationViewState.java b/src/com/android/mail/ui/ConversationViewState.java
index dc7dca8..2d733fa 100644
--- a/src/com/android/mail/ui/ConversationViewState.java
+++ b/src/com/android/mail/ui/ConversationViewState.java
@@ -34,7 +34,7 @@
* A small class to keep state for conversation view when restoring.
*
*/
-class ConversationViewState implements Parcelable {
+public class ConversationViewState implements Parcelable {
// N.B. don't serialize entire Messages because they contain body HTML/text
diff --git a/src/com/android/mail/ui/DividedImageCanvas.java b/src/com/android/mail/ui/DividedImageCanvas.java
index 2880ea4..b45e88b 100644
--- a/src/com/android/mail/ui/DividedImageCanvas.java
+++ b/src/com/android/mail/ui/DividedImageCanvas.java
@@ -20,6 +20,7 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
@@ -378,6 +379,15 @@
}
}
+ /**
+ * Draw the contents of the DividedImageCanvas to the supplied canvas.
+ */
+ public void draw(final Canvas canvas, final Matrix matrix) {
+ if (mDividedBitmap != null && mBitmapValid) {
+ canvas.drawBitmap(mDividedBitmap, matrix, null);
+ }
+ }
+
@Override
public void reset() {
if (mCanvas != null && mDividedBitmap != null) {
diff --git a/src/com/android/mail/ui/FolderDisplayer.java b/src/com/android/mail/ui/FolderDisplayer.java
index 2e12074..019c662 100644
--- a/src/com/android/mail/ui/FolderDisplayer.java
+++ b/src/com/android/mail/ui/FolderDisplayer.java
@@ -17,11 +17,11 @@
package com.android.mail.ui;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogTag;
import com.google.common.collect.Sets;
import android.content.Context;
-import android.net.Uri;
import com.android.mail.R;
import com.android.mail.providers.Conversation;
@@ -57,7 +57,7 @@
* @param ignoreFolderUri (optional) folder to omit from the displayed set
* @param ignoreFolderType -1, or the {@link FolderType} to omit from the displayed set
*/
- public void loadConversationFolders(Conversation conv, final Uri ignoreFolderUri,
+ public void loadConversationFolders(Conversation conv, final FolderUri ignoreFolderUri,
final int ignoreFolderType) {
mFoldersSortedSet.clear();
for (Folder folder : conv.getRawFolders()) {
@@ -66,7 +66,7 @@
continue;
}
// skip the ignoreFolder
- if (ignoreFolderUri != null && ignoreFolderUri.equals(folder.uri)) {
+ if (ignoreFolderUri != null && ignoreFolderUri.equals(folder.folderUri)) {
continue;
}
mFoldersSortedSet.add(folder);
diff --git a/src/com/android/mail/ui/FolderItemView.java b/src/com/android/mail/ui/FolderItemView.java
index ef0cfee..1a4cf75 100644
--- a/src/com/android/mail/ui/FolderItemView.java
+++ b/src/com/android/mail/ui/FolderItemView.java
@@ -103,7 +103,7 @@
// a is not null because it would have returned above.
return false;
}
- return (a == b || (a.uri.equals(b.uri)
+ return (a == b || (a.folderUri.equals(b.folderUri)
&& a.name.equals(b.name)
&& a.hasChildren == b.hasChildren
&& a.unseenCount == b.unseenCount
diff --git a/src/com/android/mail/ui/FolderListFragment.java b/src/com/android/mail/ui/FolderListFragment.java
index 55a0924..b153715 100644
--- a/src/com/android/mail/ui/FolderListFragment.java
+++ b/src/com/android/mail/ui/FolderListFragment.java
@@ -46,6 +46,7 @@
import com.android.mail.providers.RecentFolderObserver;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.FolderType;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
@@ -109,7 +110,7 @@
private AccountController mAccountController;
/** The currently selected folder (the folder being viewed). This is never null. */
- private Uri mSelectedFolderUri = Uri.EMPTY;
+ private FolderUri mSelectedFolderUri = FolderUri.EMPTY;
/**
* The current folder from the controller. This is meant only to check when the unread count
* goes out of sync and fixing it.
@@ -268,7 +269,8 @@
selectedFolder = currentFolder;
}
// Is the selected folder fresher than the one we have restored from a bundle?
- if (selectedFolder != null && !selectedFolder.uri.equals(mSelectedFolderUri)) {
+ if (selectedFolder != null
+ && !selectedFolder.folderUri.equals(mSelectedFolderUri)) {
setSelectedFolder(selectedFolder);
}
@@ -352,10 +354,11 @@
mListView.onRestoreInstanceState(savedState.getParcelable(BUNDLE_LIST_STATE));
}
if (savedState != null && savedState.containsKey(BUNDLE_SELECTED_FOLDER)) {
- mSelectedFolderUri = Uri.parse(savedState.getString(BUNDLE_SELECTED_FOLDER));
+ mSelectedFolderUri =
+ new FolderUri(Uri.parse(savedState.getString(BUNDLE_SELECTED_FOLDER)));
mSelectedFolderType = savedState.getInt(BUNDLE_SELECTED_TYPE);
} else if (mParentFolder != null) {
- mSelectedFolderUri = mParentFolder.uri;
+ mSelectedFolderUri = mParentFolder.folderUri;
// No selected folder type required for hierarchical lists.
}
@@ -486,7 +489,7 @@
// Not changing the account.
final Account nextAccount = null;
// Go to the conversation list for this folder.
- if (!folder.uri.equals(mSelectedFolderUri)) {
+ if (!folder.folderUri.equals(mSelectedFolderUri)) {
mNextFolder = folder;
mAccountController.closeDrawer(true, nextAccount, folder);
} else {
@@ -942,7 +945,7 @@
private static final int PARENT = 0;
private static final int CHILD = 1;
- private final Uri mParentUri;
+ private final FolderUri mParentUri;
private final Folder mParent;
private final FolderItemView.DropHandler mDropHandler;
@@ -950,7 +953,7 @@
super(mActivity.getActivityContext(), R.layout.folder_item);
mDropHandler = mActivity;
mParent = parentFolder;
- mParentUri = parentFolder.uri;
+ mParentUri = parentFolder.folderUri;
setCursor(c);
}
@@ -963,14 +966,14 @@
@Override
public int getItemViewType(int position) {
final Folder f = getItem(position);
- return f.uri.equals(mParentUri) ? PARENT : CHILD;
+ return f.folderUri.equals(mParentUri) ? PARENT : CHILD;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final FolderItemView folderItemView;
final Folder folder = getItem(position);
- boolean isParent = folder.uri.equals(mParentUri);
+ boolean isParent = folder.folderUri.equals(mParentUri);
if (convertView != null) {
folderItemView = (FolderItemView) convertView;
} else {
@@ -979,7 +982,7 @@
mActivity.getActivityContext()).inflate(resId, null);
}
folderItemView.bind(folder, mDropHandler);
- if (folder.uri.equals(mSelectedFolderUri)) {
+ if (folder.folderUri.equals(mSelectedFolderUri)) {
getListView().setItemChecked(position, true);
// If this is the current folder, also check to verify that the unread count
// matches what the action bar shows.
@@ -1045,7 +1048,7 @@
*/
private void setSelectedFolder(Folder folder) {
if (folder == null) {
- mSelectedFolderUri = Uri.EMPTY;
+ mSelectedFolderUri = FolderUri.EMPTY;
mCurrentFolderForUnreadCheck = null;
LogUtils.e(LOG_TAG, "FolderListFragment.setSelectedFolder(null) called!");
return;
@@ -1062,13 +1065,13 @@
// default inbox already, back exits the app.)
// In both these cases, the selected folder type is not set, and must be set.
if (mSelectedFolderType == DrawerItem.UNSET || (mCurrentAccount != null
- && folder.uri.equals(mCurrentAccount.settings.defaultInbox))) {
+ && folder.folderUri.equals(mCurrentAccount.settings.defaultInbox))) {
mSelectedFolderType =
folder.isInbox() ? DrawerItem.FOLDER_INBOX : DrawerItem.FOLDER_OTHER;
}
mCurrentFolderForUnreadCheck = folder;
- mSelectedFolderUri = folder.uri;
+ mSelectedFolderUri = folder.folderUri;
if (mCursorAdapter != null && viewChanged) {
mCursorAdapter.notifyDataSetChanged();
}
diff --git a/src/com/android/mail/ui/FolderOperation.java b/src/com/android/mail/ui/FolderOperation.java
index 28fef50..3dc61b8 100644
--- a/src/com/android/mail/ui/FolderOperation.java
+++ b/src/com/android/mail/ui/FolderOperation.java
@@ -68,7 +68,7 @@
*/
public static boolean isDestructive(Collection<FolderOperation> folderOps, Folder folder) {
for (FolderOperation op : folderOps) {
- if (Objects.equal(op.mFolder.uri, folder.uri) && !op.mAdd) {
+ if (Objects.equal(op.mFolder, folder) && !op.mAdd) {
return true;
}
if (folder.isTrash() && op.mFolder.isInbox()) {
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index 743afc7..93c3f08 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -248,8 +248,9 @@
* Create a widget for the specified account and folder
*/
protected void createWidget(int id, Account account, Folder selectedFolder) {
- WidgetProvider.updateWidget(this, id, account, selectedFolder.type, selectedFolder.uri,
- selectedFolder.conversationListUri, selectedFolder.name);
+ WidgetProvider.updateWidget(this, id, account, selectedFolder.type,
+ selectedFolder.folderUri.fullUri, selectedFolder.conversationListUri,
+ selectedFolder.name);
final Intent result = new Intent();
result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
setResult(RESULT_OK, result);
@@ -279,8 +280,8 @@
* account, calculate the human readable name of the folder and
* use it as the shortcut name, etc...
*/
- final Intent clickIntent = Utils.createViewFolderIntent(this, mSelectedFolder.uri,
- mAccount);
+ final Intent clickIntent = Utils.createViewFolderIntent(this,
+ mSelectedFolder.folderUri.fullUri, mAccount);
resultIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, clickIntent);
resultIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
Intent.ShortcutIconResource.fromContext(this,
diff --git a/src/com/android/mail/ui/FolderSelectorAdapter.java b/src/com/android/mail/ui/FolderSelectorAdapter.java
index 96e1d56..30451ad 100644
--- a/src/com/android/mail/ui/FolderSelectorAdapter.java
+++ b/src/com/android/mail/ui/FolderSelectorAdapter.java
@@ -115,7 +115,8 @@
do {
final Folder folder = new Folder(folders);
final boolean isSelected = initiallySelected != null
- && initiallySelected.contains(folder.uri.toString());
+ && initiallySelected.contains(
+ folder.folderUri.getComparisonUri().toString());
if (meetsRequirements(folder) && !Objects.equal(folder, mExcludedFolder)) {
final FolderRow row = new FolderRow(folder, isSelected);
// Add the currently selected first.
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 8df8320..15105c5 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -337,11 +337,6 @@
mActionBar.setDisplayHomeAsUpEnabled(true);
setEmptyMode();
break;
- case ViewMode.FOLDER_LIST:
- closeSearchField();
- mActionBar.setDisplayHomeAsUpEnabled(true);
- setFoldersMode();
- break;
case ViewMode.WAITING_FOR_ACCOUNT_INITIALIZATION:
// We want the user to be able to switch accounts while waiting for an account
// to sync.
@@ -559,16 +554,6 @@
setFolderAndAccount(false);
}
- /**
- * Put the ActionBar in standard mode, and show the word "Folders" along with the account name
- * (if user has multiple accounts)
- */
- private void setFoldersMode() {
- setTitle(R.string.folders);
- setSubtitle(mAccount.name);
- setTitleModeFlags(ActionBar.DISPLAY_SHOW_TITLE);
- }
-
private void setSubtitle(CharSequence subtitle) {
if (!TextUtils.equals(subtitle, mActionBar.getSubtitle())) {
mActionBar.setSubtitle(subtitle);
@@ -578,13 +563,6 @@
}
}
- private void setTitle(int res) {
- mActionBar.setTitle(res);
- if (mLegacyTitle != null) {
- mLegacyTitle.setText(res);
- }
- }
-
private void setTitle(CharSequence title) {
if (!TextUtils.equals(title, mActionBar.getTitle())) {
mActionBar.setTitle(title);
@@ -770,7 +748,7 @@
return;
}
/** True if we are changing folders. */
- final boolean changingFolders = (mFolder == null || !mFolder.uri.equals(folder.uri));
+ final boolean changingFolders = (mFolder == null || !mFolder.equals(folder));
mFolder = folder;
setFolderAndAccount(changingFolders);
final ConversationListContext listContext = mController == null ? null :
diff --git a/src/com/android/mail/ui/MailActivity.java b/src/com/android/mail/ui/MailActivity.java
index 036d32b..860a279 100644
--- a/src/com/android/mail/ui/MailActivity.java
+++ b/src/com/android/mail/ui/MailActivity.java
@@ -60,6 +60,8 @@
private boolean mAccessibilityEnabled;
private AccessibilityManager mAccessibilityManager;
+ protected ConversationListHelper mConversationListHelper;
+
/**
* The account name currently in use. Used to construct the NFC mailto: message. This needs
* to be static since the {@link ComposeActivity} needs to statically change the account name
@@ -105,6 +107,7 @@
public MailActivity() {
super();
+ mConversationListHelper = new ConversationListHelper();
}
@Override
@@ -423,8 +426,7 @@
}
@Override
- public ConversationListHelper getConversationListHelper() {
- // Unsupported
- return null;
+ public final ConversationListHelper getConversationListHelper() {
+ return mConversationListHelper;
}
}
diff --git a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
index b1b9059..3fb378b 100644
--- a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
+++ b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
@@ -88,7 +88,7 @@
} else {
// There are no folders for this conversation, so it must
// belong to the folder we are currently looking at.
- checked.add(mCurrentFolder.uri.toString());
+ checked.add(mCurrentFolder.folderUri.fullUri.toString());
}
}
// TODO(mindyp) : bring this back in UR8 when Email providers
@@ -142,14 +142,15 @@
if (item instanceof FolderRow) {
((FolderRow)item).setIsPresent(false);
final Folder folder = ((FolderRow)item).getFolder();
- mOperations.put(folder.uri, new FolderOperation(folder, false));
+ mOperations.put(folder.folderUri.fullUri,
+ new FolderOperation(folder, false));
}
}
}
row.setIsPresent(add);
mAdapter.notifyDataSetChanged();
final Folder folder = row.getFolder();
- mOperations.put(folder.uri, new FolderOperation(folder, add));
+ mOperations.put(folder.folderUri.fullUri, new FolderOperation(folder, add));
}
@Override
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index df198ae..eaaaedb 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -34,6 +34,7 @@
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
@@ -44,8 +45,6 @@
// Called OnePaneActivityController in Gmail.
public final class OnePaneController extends AbstractActivityController {
- /** Key used to store {@link #mLastFolderListTransactionId}. */
- private static final String FOLDER_LIST_TRANSACTION_KEY = "folder-list-transaction";
/** Key used to store {@link #mLastInboxConversationListTransactionId} */
private static final String INBOX_CONVERSATION_LIST_TRANSACTION_KEY =
"inbox_conversation-list-transaction";
@@ -65,7 +64,6 @@
private int mLastInboxConversationListTransactionId = INVALID_ID;
private int mLastConversationListTransactionId = INVALID_ID;
private int mLastConversationTransactionId = INVALID_ID;
- private int mLastFolderListTransactionId = INVALID_ID;
private Folder mInbox;
/** Whether a conversation list for this account has ever been shown.*/
private boolean mConversationListNeverShown = true;
@@ -80,7 +78,6 @@
if (inState == null) {
return;
}
- mLastFolderListTransactionId = inState.getInt(FOLDER_LIST_TRANSACTION_KEY, INVALID_ID);
mLastInboxConversationListTransactionId =
inState.getInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY, INVALID_ID);
mLastConversationListTransactionId =
@@ -94,7 +91,6 @@
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putInt(FOLDER_LIST_TRANSACTION_KEY, mLastFolderListTransactionId);
outState.putInt(INBOX_CONVERSATION_LIST_TRANSACTION_KEY,
mLastInboxConversationListTransactionId);
outState.putInt(CONVERSATION_LIST_TRANSACTION_KEY, mLastConversationListTransactionId);
@@ -117,7 +113,7 @@
* @param account the account whose default Inbox the candidate might be
* @return true if the candidate is indeed the default inbox for the given account.
*/
- private static boolean isDefaultInbox(Uri candidate, Account account) {
+ private static boolean isDefaultInbox(FolderUri candidate, Account account) {
return (candidate != null && account != null)
&& candidate.equals(account.settings.defaultInbox);
}
@@ -131,7 +127,7 @@
// If we don't have valid state, then we are not in the inbox.
return !(account == null || context == null || context.folder == null
|| account.settings == null) && !ConversationListContext.isSearchResult(context)
- && isDefaultInbox(context.folder.uri, account);
+ && isDefaultInbox(context.folder.folderUri, account);
}
/**
@@ -180,8 +176,6 @@
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(super.toString());
- sb.append("{lastFolderListTransId=");
- sb.append(mLastFolderListTransactionId);
sb.append(" lastInboxTransId=");
sb.append(mLastInboxConversationListTransactionId);
sb.append(" lastConvListTransId=");
@@ -217,11 +211,6 @@
mLastInboxConversationListTransactionId = replaceFragmentWithBack(
conversationListFragment, transition, TAG_CONVERSATION_LIST, R.id.content_pane);
- // FIXME: "forgetting" the folder list entry in the back stack doesn't remove it from
- // the back stack. only popping past it can remove it.
- // Maybe we should clear the back stack prior to opening a folder.
- mLastFolderListTransactionId = INVALID_ID;
-
// If we ever to to the inbox, we want to unset the transation id for any other
// non-inbox folder.
mLastConversationListTransactionId = INVALID_ID;
@@ -357,43 +346,10 @@
public boolean handleBackPress() {
final int mode = mViewMode.getMode();
- //TODO(shahrk): Remove the folder list standalone view
- if (mode == ViewMode.FOLDER_LIST) {
- final Folder hierarchyFolder = getHierarchyFolder();
- final FolderListFragment folderListFragment = getFolderListFragment();
- final boolean parentHasChildren = folderListFragment != null &&
- folderListFragment.showingHierarchy() && hierarchyFolder != null
- && hierarchyFolder.parent != Uri.EMPTY;
- if (parentHasChildren) {
- // If we are showing the folder list and the user is exploring
- // the children of a single parent folder,
- // back should display the parent folder's parent and siblings.
- goUpFolderHierarchy(hierarchyFolder);
- } else {
- // We are at the topmost list of folders: go back
- mLastFolderListTransactionId = INVALID_ID;
- transitionToInbox();
- }
- } else if (mode == ViewMode.SEARCH_RESULTS_LIST) {
+ if (mode == ViewMode.SEARCH_RESULTS_LIST) {
mActivity.finish();
} else if (mViewMode.isListMode() && !inInbox(mAccount, mConvListContext)) {
- if (mLastFolderListTransactionId != INVALID_ID) {
- // Set the hierarchy folder to what it will be once we go up
-
- // The hierarchy folder stuff is not required. We need to clean this stuff up.
- // TODO: http://b/9694899
-// final Folder hierarchyFolder = getHierarchyFolder();
-// if (hierarchyFolder != null && hierarchyFolder.parent != null) {
-// setHierarchyFolder(hierarchyFolder.parent);
-// }
-
- // If the user got here by navigating via the folder list, back
- // should bring them back to the folder list.
- mViewMode.enterFolderListMode();
- mActivity.getFragmentManager().popBackStack(mLastFolderListTransactionId, 0);
- } else {
- transitionToInbox();
- }
+ transitionToInbox();
} else if (mViewMode.isConversationMode()) {
transitionBackToConversationListMode(false /* inLoaderCallbacks */);
} else {
@@ -441,7 +397,7 @@
*/
private void transitionToInbox() {
// The inbox could have changed, in which case we should load it again.
- if (mInbox == null || !isDefaultInbox(mInbox.uri, mAccount)) {
+ if (mInbox == null || !isDefaultInbox(mInbox.folderUri, mAccount)) {
loadAccountInbox();
} else {
onFolderChanged(mInbox);
@@ -487,27 +443,11 @@
return true;
}
- if (mode == ViewMode.CONVERSATION
- || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
+ if (mode == ViewMode.CONVERSATION || mode == ViewMode.SEARCH_RESULTS_CONVERSATION) {
// Same as go back.
handleBackPress();
return true;
}
- if (mode == ViewMode.FOLDER_LIST) {
- // If the folder is the top level of an heirarchy or flat, toggle the
- // state of the drawer. Otherwise, let it pass on as a back press.
- // We don't want this code in back press, otherwise pressing back
- // will exhibit the same behavior
- final FolderListFragment folderListFragment = getFolderListFragment();
- if (folderListFragment != null) {
- final Folder parentFolder = folderListFragment.getParentFolder();
- if (parentFolder == null || parentFolder.parent == Uri.EMPTY) {
- toggleFolderListState();
- return true;
- }
- }
- handleBackPress();
- }
return true;
}
@@ -628,16 +568,6 @@
}
}
- @Override
- public String getHelpContext() {
- final int mode = mViewMode.getMode();
- switch (mode) {
- case ViewMode.FOLDER_LIST:
- return mContext.getString(R.string.one_pane_folder_list_help_context);
- }
- return super.getHelpContext();
- }
-
private final class PopBackStackRunnable implements Runnable {
private final int mTransactionId;
diff --git a/src/com/android/mail/ui/RecentFolderList.java b/src/com/android/mail/ui/RecentFolderList.java
index e09b08a..25f3568 100644
--- a/src/com/android/mail/ui/RecentFolderList.java
+++ b/src/com/android/mail/ui/RecentFolderList.java
@@ -26,6 +26,7 @@
import com.android.mail.providers.AccountObserver;
import com.android.mail.providers.Folder;
import com.android.mail.providers.Settings;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.LruCache;
import com.android.mail.utils.Utils;
@@ -112,7 +113,7 @@
ContentValues values = new ContentValues();
// Only the folder URIs are provided. Providers are free to update their specific
// information, though most will probably write the current timestamp.
- values.put(mFolder.uri.toString(), 0);
+ values.put(mFolder.folderUri.fullUri.toString(), 0);
LogUtils.i(TAG, "Save: %s", mFolder.name);
mContext.getContentResolver().update(uri, values, null, null);
}
@@ -176,7 +177,7 @@
do {
final Folder folder = c.getModel();
final RecentFolderListEntry entry = new RecentFolderListEntry(folder);
- mFolderCache.putElement(folder.uri.toString(), entry);
+ mFolderCache.putElement(folder.folderUri.fullUri.toString(), entry);
LogUtils.v(TAG, "Account %s, Recent: %s", mAccount.name, folder.name);
} while (c.moveToPrevious());
}
@@ -205,7 +206,7 @@
}
final RecentFolderListEntry entry = new RecentFolderListEntry(folder);
- mFolderCache.putElement(folder.uri.toString(), entry);
+ mFolderCache.putElement(folder.folderUri.fullUri.toString(), entry);
new StoreRecent(mAccount, folder).execute();
}
@@ -216,14 +217,15 @@
* Returns a list of size {@value #MAX_RECENT_FOLDERS} or smaller.
* @param excludedFolderUri the uri of folder to be excluded (typically the current folder)
*/
- public ArrayList<Folder> getRecentFolderList(Uri excludedFolderUri) {
- final ArrayList<Uri> excludedUris = new ArrayList<Uri>();
+ public ArrayList<Folder> getRecentFolderList(final FolderUri excludedFolderUri) {
+ final ArrayList<FolderUri> excludedUris = new ArrayList<FolderUri>();
if (excludedFolderUri != null) {
excludedUris.add(excludedFolderUri);
}
- final Uri defaultInbox = (mAccount == null) ?
- Uri.EMPTY : Settings.getDefaultInboxUri(mAccount.settings);
- if (!defaultInbox.equals(Uri.EMPTY)) {
+ final FolderUri defaultInbox = (mAccount == null)
+ ? FolderUri.EMPTY
+ : new FolderUri(Settings.getDefaultInboxUri(mAccount.settings));
+ if (!defaultInbox.equals(FolderUri.EMPTY)) {
excludedUris.add(defaultInbox);
}
final List<RecentFolderListEntry> recent = Lists.newArrayList();
@@ -232,7 +234,7 @@
final ArrayList<Folder> recentFolders = Lists.newArrayList();
for (final RecentFolderListEntry entry : recent) {
- if (!excludedUris.contains(entry.mFolder.uri)) {
+ if (!excludedUris.contains(entry.mFolder.folderUri)) {
recentFolders.add(entry.mFolder);
}
if (recentFolders.size() == MAX_RECENT_FOLDERS) {
diff --git a/src/com/android/mail/ui/SecureConversationViewController.java b/src/com/android/mail/ui/SecureConversationViewController.java
index f049168..56f590e 100644
--- a/src/com/android/mail/ui/SecureConversationViewController.java
+++ b/src/com/android/mail/ui/SecureConversationViewController.java
@@ -18,6 +18,7 @@
package com.android.mail.ui;
import android.app.Fragment;
+import android.app.FragmentManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -206,5 +207,10 @@
return null;
}
+ @Override
+ public FragmentManager getFragmentManager() {
+ return mCallbacks.getFragment().getFragmentManager();
+ }
+
// End MessageHeaderViewCallbacks implementations
}
diff --git a/src/com/android/mail/ui/SuppressNotificationReceiver.java b/src/com/android/mail/ui/SuppressNotificationReceiver.java
index a2d94e7..685edd0 100644
--- a/src/com/android/mail/ui/SuppressNotificationReceiver.java
+++ b/src/com/android/mail/ui/SuppressNotificationReceiver.java
@@ -146,7 +146,7 @@
final Uri intentFolderUri =
(Uri)intent.getParcelableExtra(UIProvider.UpdateNotificationExtras.EXTRA_FOLDER);
- if (!listContextFolder.uri.equals(intentFolderUri)) {
+ if (!listContextFolder.folderUri.equals(intentFolderUri)) {
return;
}
final int count = intent.getIntExtra(
diff --git a/src/com/android/mail/ui/SwipeableListView.java b/src/com/android/mail/ui/SwipeableListView.java
index 24189fd..e184e41 100644
--- a/src/com/android/mail/ui/SwipeableListView.java
+++ b/src/com/android/mail/ui/SwipeableListView.java
@@ -79,11 +79,11 @@
public SwipeableListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ setOnScrollListener(this);
float densityScale = getResources().getDisplayMetrics().density;
float pagingTouchSlop = ViewConfiguration.get(context).getScaledPagingTouchSlop();
mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale,
pagingTouchSlop);
- setOnScrollListener(this);
}
@Override
@@ -224,12 +224,12 @@
FolderOperation folderOp = new FolderOperation(mFolder, false);
HashMap<Uri, Folder> targetFolders = Folder
.hashMapForFolders(conv.getRawFolders());
- targetFolders.remove(folderOp.mFolder.uri);
+ targetFolders.remove(folderOp.mFolder.folderUri.fullUri);
final FolderList folders = FolderList.copyOf(targetFolders.values());
conv.setRawFolders(folders);
final ContentValues values = new ContentValues();
folderUris = new ArrayList<Uri>();
- folderUris.add(mFolder.uri);
+ folderUris.add(mFolder.folderUri.fullUri);
adds = new ArrayList<Boolean>();
adds.add(Boolean.FALSE);
ConversationCursor.addFolderUpdates(folderUris, adds, values);
@@ -341,11 +341,9 @@
// Superclass method modifies the selection set
final boolean handled = super.performItemClick(view, pos, id);
- // If we are in CAB mode with no checkboxes then a click shouldn't
+ // If we are in CAB mode then a click shouldn't
// activate the new item, it should only add it to the selection set
- final boolean showSenderImage = mAccount != null
- && (mAccount.settings.convListIcon == ConversationListIcon.SENDER_IMAGE);
- if (!showSenderImage && !selectionSetEmpty && previousPosition != -1) {
+ if (!selectionSetEmpty && previousPosition != -1) {
setItemChecked(previousPosition, true);
}
// Commit any existing destructive actions when the user selects a
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index e579292..91a3ccf 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -423,7 +423,7 @@
}
final boolean shouldLoadInbox = mode == ViewMode.CONVERSATION_LIST &&
mAccount != null && mFolder != null &&
- !mAccount.settings.defaultInbox.equals(mFolder.uri) &&
+ !mFolder.folderUri.equals(mAccount.settings.defaultInbox) &&
mLayout != null && !mLayout.isExpansiveLayout();
if (shouldLoadInbox) {
loadAccountInbox();
diff --git a/src/com/android/mail/ui/ViewMode.java b/src/com/android/mail/ui/ViewMode.java
index ec43039..aee794d 100644
--- a/src/com/android/mail/ui/ViewMode.java
+++ b/src/com/android/mail/ui/ViewMode.java
@@ -50,21 +50,17 @@
*/
public static final int CONVERSATION_LIST = 2;
/**
- * Mode when showing a list of folders.
+ * Mode when showing results from user search.
*/
- public static final int FOLDER_LIST = 3;
+ public static final int SEARCH_RESULTS_LIST = 3;
/**
* Mode when showing results from user search.
*/
- public static final int SEARCH_RESULTS_LIST = 4;
- /**
- * Mode when showing results from user search.
- */
- public static final int SEARCH_RESULTS_CONVERSATION = 5;
+ public static final int SEARCH_RESULTS_CONVERSATION = 4;
/**
* Mode when showing the "waiting for sync" message.
*/
- public static final int WAITING_FOR_ACCOUNT_INITIALIZATION = 6;
+ public static final int WAITING_FOR_ACCOUNT_INITIALIZATION = 5;
/**
* Uncertain mode. The mode has not been initialized.
*/
@@ -127,14 +123,6 @@
}
/**
- * Requests a transition of the mode to show the folder list as the prominent view.
- *
- */
- public void enterFolderListMode() {
- setModeInternal(FOLDER_LIST);
- }
-
- /**
* Requests a transition of the mode to show a list of search results as the
* prominent view.
*
diff --git a/src/com/android/mail/utils/AttachmentUtils.java b/src/com/android/mail/utils/AttachmentUtils.java
index b66be9b..26adee8 100644
--- a/src/com/android/mail/utils/AttachmentUtils.java
+++ b/src/com/android/mail/utils/AttachmentUtils.java
@@ -30,6 +30,7 @@
import com.android.mail.providers.Attachment;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
@@ -190,6 +191,13 @@
// Get the input stream from the file descriptor
inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
} else {
+ if (attachment.contentUri == null) {
+ // The contentUri of the attachment is null. This can happen when sending a
+ // message that has been previously saved, and the attachments had been
+ // uploaded.
+ LogUtils.d(LOG_TAG, "contentUri is null in attachment: %s", attachment);
+ throw new FileNotFoundException("Missing contentUri in attachment");
+ }
// Attempt to open the file
inputStream = context.getContentResolver().openInputStream(attachment.contentUri);
}
diff --git a/src/com/android/mail/utils/FolderUri.java b/src/com/android/mail/utils/FolderUri.java
new file mode 100644
index 0000000..d4d43ee
--- /dev/null
+++ b/src/com/android/mail/utils/FolderUri.java
@@ -0,0 +1,77 @@
+/*
+ * 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.utils;
+
+import android.net.Uri;
+
+/**
+ * A holder for a Folder {@link Uri} that can be compared, ignoring any query parameters.
+ */
+public class FolderUri {
+ public static final FolderUri EMPTY = new FolderUri(Uri.EMPTY);
+
+ /**
+ * The full {@link Uri}. This should be used for any queries.
+ */
+ public final Uri fullUri;
+ /**
+ * Equivalent to {@link #fullUri}, but without any query parameters, and can safely be used in
+ * comparisons to determine if two {@link Uri}s point to the same object.
+ */
+ private Uri mComparisonUri = null;
+
+ public FolderUri(final Uri uri) {
+ fullUri = uri;
+ }
+
+ private static Uri buildComparisonUri(final Uri fullUri) {
+ final Uri.Builder builder = new Uri.Builder();
+ builder.scheme(fullUri .getScheme());
+ builder.encodedAuthority(fullUri.getEncodedAuthority());
+ builder.encodedPath(fullUri.getEncodedPath());
+
+ return builder.build();
+ }
+
+ public Uri getComparisonUri() {
+ if (mComparisonUri == null) {
+ mComparisonUri = buildComparisonUri(fullUri);
+ }
+
+ return mComparisonUri;
+ }
+
+ @Override
+ public int hashCode() {
+ return getComparisonUri().hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (o instanceof FolderUri) {
+ return getComparisonUri().equals(((FolderUri) o).getComparisonUri());
+ }
+
+ return getComparisonUri().equals(o);
+ }
+
+ @Override
+ public String toString() {
+ return fullUri.toString();
+ }
+}
diff --git a/src/com/android/mail/utils/NotificationActionUtils.java b/src/com/android/mail/utils/NotificationActionUtils.java
index f3246f9..3c0e42a 100644
--- a/src/com/android/mail/utils/NotificationActionUtils.java
+++ b/src/com/android/mail/utils/NotificationActionUtils.java
@@ -632,8 +632,8 @@
// Not inbox, so remove label
final ContentValues values = new ContentValues(1);
- final String removeFolderUri =
- folder.uri.buildUpon().appendPath(Boolean.FALSE.toString()).toString();
+ final String removeFolderUri = folder.folderUri.fullUri.buildUpon()
+ .appendPath(Boolean.FALSE.toString()).toString();
values.put(ConversationOperations.FOLDERS_UPDATED, removeFolderUri);
contentResolver.update(uri, values, null, null);
@@ -729,7 +729,7 @@
final Intent intent = new Intent(MailIntentService.ACTION_RESEND_NOTIFICATIONS);
intent.setPackage(context.getPackageName()); // Make sure we only deliver this to ourself
intent.putExtra(Utils.EXTRA_ACCOUNT_URI, account.uri);
- intent.putExtra(Utils.EXTRA_FOLDER_URI, folder.uri);
+ intent.putExtra(Utils.EXTRA_FOLDER_URI, folder.folderUri.fullUri);
context.startService(intent);
}
diff --git a/src/com/android/mail/utils/NotificationUtils.java b/src/com/android/mail/utils/NotificationUtils.java
index e38a64e..4889651 100644
--- a/src/com/android/mail/utils/NotificationUtils.java
+++ b/src/com/android/mail/utils/NotificationUtils.java
@@ -218,7 +218,7 @@
final Integer unseenCount = value.second;
if (unreadCount != null && unseenCount != null) {
final String[] partValues = new String[] {
- key.account.uri.toString(), key.folder.uri.toString(),
+ key.account.uri.toString(), key.folder.folderUri.fullUri.toString(),
unreadCount.toString(), unseenCount.toString()};
notificationSet.add(TextUtils.join(NOTIFICATION_PART_SEPARATOR, partValues));
}
@@ -291,7 +291,7 @@
* upon which an action occurred.
*/
public static void resendNotifications(Context context, final boolean cancelExisting,
- final Uri accountUri, final Uri folderUri) {
+ final Uri accountUri, final FolderUri folderUri) {
LogUtils.d(LOG_TAG, "NotificationUtils: resendNotifications ");
if (cancelExisting) {
@@ -311,15 +311,15 @@
// Only resend notifications if the notifications are from the same folder
// and same account as the undo notification that was previously displayed.
if (accountUri != null && !Objects.equal(accountUri, notification.account.uri) &&
- folderUri != null && !Objects.equal(folderUri, folder.uri)) {
+ folderUri != null && !Objects.equal(folderUri, folder.folderUri)) {
LogUtils.d(LOG_TAG, "NotificationUtils: resendNotifications - not resending %s / %s"
+ " because it doesn't match %s / %s",
- notification.account.uri, folder.uri, accountUri, folderUri);
+ notification.account.uri, folder.folderUri, accountUri, folderUri);
continue;
}
LogUtils.d(LOG_TAG, "NotificationUtils: resendNotifications - resending %s / %s",
- notification.account.uri, folder.uri);
+ notification.account.uri, folder.folderUri);
final NotificationAction undoableAction =
NotificationActionUtils.sUndoNotifications.get(notificationId);
@@ -361,8 +361,8 @@
// If notification is not enabled for this label, remember this NotificationKey
// to later cancel the notification, and remove the entry from the map
final Folder folder = notification.folder;
- final boolean isInbox =
- notification.account.settings.defaultInbox.equals(folder.uri);
+ final boolean isInbox = folder.folderUri.equals(
+ notification.account.settings.defaultInbox);
final FolderPreferences folderPreferences = new FolderPreferences(
context, notification.account.name, folder, isInbox);
@@ -400,7 +400,7 @@
final boolean getAttention) {
LogUtils.d(LOG_TAG, "NotificationUtils: setNewEmailIndicator unreadCount = %d, "
+ "unseenCount = %d, account = %s, folder = %s, getAttention = %b", unreadCount,
- unseenCount, account.name, folder.uri, getAttention);
+ unseenCount, account.name, folder.folderUri, getAttention);
boolean ignoreUnobtrusiveSetting = false;
@@ -535,7 +535,7 @@
new Intent(MailIntentService.ACTION_CLEAR_NEW_MAIL_NOTIFICATIONS);
cancelNotificationIntent.setPackage(context.getPackageName());
cancelNotificationIntent.setData(Utils.appendVersionQueryParameter(context,
- folder.uri));
+ folder.folderUri.fullUri));
cancelNotificationIntent.putExtra(Utils.EXTRA_ACCOUNT, account);
cancelNotificationIntent.putExtra(Utils.EXTRA_FOLDER, folder);
@@ -547,7 +547,7 @@
boolean eventInfoConfigured = false;
- final boolean isInbox = account.settings.defaultInbox.equals(folder.uri);
+ final boolean isInbox = folder.folderUri.equals(account.settings.defaultInbox);
final FolderPreferences folderPreferences =
new FolderPreferences(context, account.name, folder, isInbox);
@@ -659,15 +659,15 @@
final Intent intent;
if (cursor == null) {
- intent = Utils.createViewFolderIntent(context, folder.uri, account);
+ intent = Utils.createViewFolderIntent(context, folder.folderUri.fullUri, account);
} else {
// A conversation cursor has been specified, so this intent is intended to be go
// directly to the one new conversation
// Get the Conversation object
final Conversation conversation = new Conversation(cursor);
- intent = Utils.createViewConversationIntent(context, conversation, folder.uri,
- account);
+ intent = Utils.createViewConversationIntent(context, conversation,
+ folder.folderUri.fullUri, account);
}
return intent;
@@ -719,7 +719,7 @@
String notificationTicker = null;
// Boolean indicating that this notification is for a non-inbox label.
- final boolean isInbox = account.settings.defaultInbox.equals(folder.uri);
+ final boolean isInbox = folder.folderUri.fullUri.equals(account.settings.defaultInbox);
// Notification label name for user label notifications.
final String notificationLabelName = isInbox ? null : folder.name;
@@ -1376,7 +1376,7 @@
}
public static void markSeen(final Context context, final Folder folder) {
- final Uri uri = folder.uri;
+ final Uri uri = folder.folderUri.fullUri;
final ContentValues values = new ContentValues(1);
values.put(UIProvider.ConversationColumns.SEEN, 1);
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index 4fa8f7d..251e95e 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -99,6 +99,8 @@
public static final String EXTRA_COMPOSE_URI = "composeUri";
public static final String EXTRA_CONVERSATION = "conversationUri";
+ private static final String MAILTO_SCHEME = "mailto";
+
/** Extra tag for debugging the blank fragment problem. */
public static final String VIEW_DEBUGGING_TAG = "MailBlankFragment";
@@ -1285,6 +1287,15 @@
}
/**
+ * Adds the Account extra to mailto intents.
+ */
+ public static void addAccountToMailtoIntent(Intent intent, Account account) {
+ if (TextUtils.equals(MAILTO_SCHEME, intent.getData().getScheme())) {
+ intent.putExtra(Utils.EXTRA_ACCOUNT, account);
+ }
+ }
+
+ /**
* Gets the specified {@link Folder} object.
*
* @param folderUri The {@link Uri} for the folder
diff --git a/src/com/android/mail/widget/WidgetConversationViewBuilder.java b/src/com/android/mail/widget/WidgetConversationViewBuilder.java
index 45c4cd9..77c1992 100644
--- a/src/com/android/mail/widget/WidgetConversationViewBuilder.java
+++ b/src/com/android/mail/widget/WidgetConversationViewBuilder.java
@@ -20,13 +20,13 @@
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.ui.FolderDisplayer;
+import com.android.mail.utils.FolderUri;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
-import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.AbsoluteSizeSpan;
@@ -66,7 +66,7 @@
* Load Conversation Labels
*/
@Override
- public void loadConversationFolders(Conversation conv, final Uri ignoreFolderUri,
+ public void loadConversationFolders(Conversation conv, final FolderUri ignoreFolderUri,
final int ignoreFolderType) {
super.loadConversationFolders(conv, ignoreFolderUri, ignoreFolderType);
}
@@ -147,8 +147,8 @@
* Return the full View
*/
public RemoteViews getStyledView(CharSequence date, Conversation conversation,
- final Uri folderUri, final int ignoreFolderType, SpannableStringBuilder senders,
- String filteredSubject) {
+ final FolderUri folderUri, final int ignoreFolderType,
+ SpannableStringBuilder senders, String filteredSubject) {
final boolean isUnread = !conversation.read;
String snippet = conversation.getSnippet();
diff --git a/src/com/android/mail/widget/WidgetService.java b/src/com/android/mail/widget/WidgetService.java
index 7d19c68..a8a45f3 100644
--- a/src/com/android/mail/widget/WidgetService.java
+++ b/src/com/android/mail/widget/WidgetService.java
@@ -48,6 +48,7 @@
import com.android.mail.providers.UIProvider.ConversationListQueryParameters;
import com.android.mail.providers.UIProvider.FolderType;
import com.android.mail.utils.AccountUtils;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.DelayedTaskHandler;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
@@ -241,7 +242,7 @@
String folderString = intent.getStringExtra(Utils.EXTRA_FOLDER);
Folder folder = Folder.fromString(folderString);
if (folder != null) {
- mFolderUri = folder.uri;
+ mFolderUri = folder.folderUri.fullUri;
mFolderConversationListUri = folder.conversationListUri;
} else {
mFolderUri = Uri.EMPTY;
@@ -414,8 +415,8 @@
// Load up our remote view.
RemoteViews remoteViews = mWidgetConversationViewBuilder.getStyledView(date,
- conversation, mFolderUri, ignoreFolderType, senderBuilder,
- filterTag(conversation.subject));
+ conversation, new FolderUri(mFolderUri), ignoreFolderType,
+ senderBuilder, filterTag(conversation.subject));
// On click intent.
remoteViews.setOnClickFillInIntent(R.id.widget_conversation,
diff --git a/tests/src/com/android/mail/compose/ComposeActivityTest.java b/tests/src/com/android/mail/compose/ComposeActivityTest.java
index f7662e9..c2c55de 100644
--- a/tests/src/com/android/mail/compose/ComposeActivityTest.java
+++ b/tests/src/com/android/mail/compose/ComposeActivityTest.java
@@ -16,6 +16,9 @@
package com.android.mail.compose;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
@@ -25,38 +28,47 @@
import android.text.TextUtils;
import android.text.util.Rfc822Tokenizer;
+import com.android.mail.compose.ComposeActivity;
import com.android.mail.providers.Account;
import com.android.mail.providers.Attachment;
+import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.Message;
import com.android.mail.providers.ReplyFromAccount;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.AccountUtils;
+import com.android.mail.utils.LogUtils;
import com.android.mail.utils.MatrixCursorWithCachedColumns;
+import com.android.mail.utils.Utils;
import org.json.JSONArray;
import org.json.JSONException;
+import java.lang.Deprecated;
+import java.lang.Throwable;
+import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
@SmallTest
public class ComposeActivityTest extends ActivityInstrumentationTestCase2<ComposeActivity> {
+ // TODO: Remove usages of FromAddressSpinner#initialize and ComposeActivity#initReplyRecipients.
+ // The internal state of the activity instance may have the wrong mReplyFromAccount as
+ // this is set when handling the initial intent. Theses tests should
+ // instantiate the ComposeActivity with the correct reply all intent
- private ComposeActivity mActivity;
+ // This varible shouldn't be used, as it may not match the state of the ComposeActivity
+ // TODO: remove usage of this variable
+ @Deprecated
private Account mAccount;
+ private static final Account[] EMPTY_ACCOUNT_LIST = new Account[0];
+
public ComposeActivityTest() {
super(ComposeActivity.class);
}
- @Override
- protected void setUp() throws Exception {
- mActivity = getActivity();
- super.setUp();
- }
-
- private Message getRefMessage() {
- Cursor foldersCursor = mActivity.getContentResolver().query(mAccount.folderListUri,
+ private Message getRefMessage(ContentResolver resolver, Uri folderListUri) {
+ Cursor foldersCursor = resolver.query(folderListUri,
UIProvider.FOLDERS_PROJECTION, null, null, null);
Uri convUri = null;
if (foldersCursor != null) {
@@ -65,7 +77,8 @@
.getString(UIProvider.FOLDER_CONVERSATION_LIST_URI_COLUMN));
foldersCursor.close();
}
- Cursor convCursor = mActivity.getContentResolver().query(convUri,
+
+ Cursor convCursor = resolver.query(convUri,
UIProvider.CONVERSATION_PROJECTION, null, null, null);
Uri messagesUri = null;
if (convCursor != null) {
@@ -74,7 +87,8 @@
.getString(UIProvider.CONVERSATION_MESSAGE_LIST_URI_COLUMN));
convCursor.close();
}
- Cursor msgCursor = mActivity.getContentResolver().query(messagesUri,
+
+ Cursor msgCursor = resolver.query(messagesUri,
UIProvider.MESSAGE_PROJECTION, null, null, null);
if (msgCursor != null) {
msgCursor.moveToFirst();
@@ -82,16 +96,32 @@
return new Message(msgCursor);
}
- public void setAccount(String accountName) {
+
+ private Message getRefMessage(ContentResolver resolver) {
+ return getRefMessage(resolver, mAccount.folderListUri);
+ }
+
+ public void setAccount(ComposeActivity activity, String accountName) {
// Get a mock account.
- Account[] results = AccountUtils.getSyncingAccounts(mActivity);
+ final Account account = getAccountForName(activity, accountName);
+ if (account != null) {
+ mAccount = account;
+ activity.setAccount(mAccount);
+ }
+ }
+
+ private Account[] getAccounts(Context context) {
+ return AccountUtils.getSyncingAccounts(context);
+ }
+
+ private Account getAccountForName(Context context, String accountName) {
+ Account[] results = getAccounts(context);
for (Account account : results) {
if (account.name.equals(accountName)) {
- mAccount = account;
- mActivity.setAccount(mAccount);
- break;
+ return account;
}
}
+ return null;
}
/**
@@ -99,17 +129,17 @@
* and they are replying all to a message where their custom from was a
* recipient. TODO: verify web behavior
*/
- public void testRecipientsRefReplyAllCustomFromReplyTo() {
- setAccount("account3@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefReplyAllCustomFromReplyTo() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account3@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String customFrom = "CUSTOMaccount3@mockuiprovider.com";
refMessage.setFrom("account3@mockuiprovider.com");
refMessage.setTo("someotheraccount1@mockuiprovider.com, "
+ "someotheraccount2@mockuiprovider.com, someotheraccount3@mockuiprovider.com, "
+ customFrom);
refMessage.setReplyTo(customFrom);
- final ComposeActivity activity = mActivity;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom,
customFrom, customFrom, true, true);
JSONArray array = new JSONArray();
@@ -117,10 +147,11 @@
mAccount.accountFromAddresses = array.toString();
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, customFrom, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
- currentAccount.account, null, null);
- mActivity.runOnUiThread(new Runnable() {
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
+ currentAccount.account, EMPTY_ACCOUNT_LIST, null);
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -140,20 +171,21 @@
* Test the cases where: The user sent a message to one of
* their custom froms and just replied to that message
*/
- public void testRecipientsRefReplyAllOnlyAccount() {
- setAccount("account3@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefReplyAllOnlyAccount() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account3@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("account3@mockuiprovider.com");
refMessage.setTo("account3@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
final Account account = mAccount;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, mAccount.name, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
- currentAccount.account, null, null);
- mActivity.runOnUiThread(new Runnable() {
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
+ currentAccount.account, EMPTY_ACCOUNT_LIST, null);
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -173,14 +205,14 @@
* Test the cases where: The user sent a message to one of
* their custom froms and just replied to that message
*/
- public void testRecipientsRefReplyAllOnlyCustomFrom() {
- setAccount("account3@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefReplyAllOnlyCustomFrom() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account3@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String customFrom = "CUSTOMaccount3@mockuiprovider.com";
refMessage.setFrom("account3@mockuiprovider.com");
refMessage.setTo(customFrom);
- final ComposeActivity activity = mActivity;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom,
customFrom, customFrom, true, true);
JSONArray array = new JSONArray();
@@ -188,10 +220,11 @@
mAccount.accountFromAddresses = array.toString();
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, customFrom, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
- currentAccount.account, null, null);
- mActivity.runOnUiThread(new Runnable() {
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
+ currentAccount.account, EMPTY_ACCOUNT_LIST, null);
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -207,13 +240,13 @@
});
}
- public void testReply() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testReply() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String refMessageFromAccount = refMessage.getFrom();
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY);
@@ -229,14 +262,14 @@
});
}
- public void testReplyWithReplyTo() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testReplyWithReplyTo() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setReplyTo("replytofromaccount1@mock.com");
- final ComposeActivity activity = mActivity;
final String refReplyToAccount = refMessage.getReplyTo();
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY);
@@ -255,13 +288,13 @@
/**
* Reply to a message you sent yourself to some recipients in the to field.
*/
- public void testReplyToSelf() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testReplyToSelf() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("Account Test <account1@mockuiprovider.com>");
refMessage.setTo("test1@gmail.com");
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY);
@@ -280,13 +313,13 @@
/**
* Reply-all to a message you sent.
*/
- public void testReplyAllToSelf() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testReplyAllToSelf() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("Account Test <account1@mockuiprovider.com>");
refMessage.setTo("test1@gmail.com, test2@gmail.com");
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -306,14 +339,14 @@
/**
* Reply-all to a message you sent with some to and some CC recips.
*/
- public void testReplyAllToSelfWithCc() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testReplyAllToSelfWithCc() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("Account Test <account1@mockuiprovider.com>");
refMessage.setTo("test1@gmail.com, test2@gmail.com");
refMessage.setCc("testcc@gmail.com");
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -332,14 +365,14 @@
});
}
- public void testReplyAll() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testReplyAll() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ",");
final String refMessageFromAccount = refMessage.getFrom();
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -355,15 +388,15 @@
});
}
- public void testReplyAllWithReplyTo() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testReplyAllWithReplyTo() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setReplyTo("replytofromaccount1@mock.com");
- final ComposeActivity activity = mActivity;
final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ",");
final String refReplyToAccount = refMessage.getReplyTo();
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -401,15 +434,15 @@
return new Message(cursor);
}
- public void testReplyAllWithCc() {
- setAccount("account1@mockuiprovider.com");
+ public void testReplyAllWithCc() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
final Message refMessage = getRefMessageWithCc(0, false);
- final ComposeActivity activity = mActivity;
final String[] refMessageTo = TextUtils.split(refMessage.getTo(), ",");
final String[] refMessageCc = TextUtils.split(refMessage.getCc(), ",");
final String refMessageFromAccount = refMessage.getFrom();
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -417,7 +450,8 @@
String[] cc = activity.getCcAddresses();
String[] bcc = activity.getBccAddresses();
assertTrue(to.length == 1);
- assertEquals(refMessageFromAccount, Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
+ assertEquals(refMessageFromAccount,
+ Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
assertEquals(cc.length, refMessageTo.length + refMessageCc.length);
HashSet<String> ccMap = new HashSet<String>();
for (String recip : cc) {
@@ -434,12 +468,12 @@
});
}
- public void testForward() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testForward() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.FORWARD);
@@ -453,12 +487,12 @@
});
}
- public void testCompose() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
- final ComposeActivity activity = mActivity;
+ public void testCompose() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.COMPOSE);
@@ -475,14 +509,14 @@
/**
* Test the cases where: The user is replying to a message they sent
*/
- public void testRecipientsRefMessageReplyToSelf() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefMessageReplyToSelf() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("account0@mockuiprovider.com");
refMessage.setTo("someotheraccount@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY);
@@ -501,13 +535,13 @@
* Test the cases where:
* The user is replying to a message sent from one of their custom froms
*/
- public void testRecipientsRefMessageReplyToCustomFrom() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefMessageReplyToCustomFrom() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("CUSTOMaccount1@mockuiprovider.com");
refMessage.setTo("someotheraccount@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, refMessage.getFrom(),
refMessage.getFrom(), refMessage.getFrom(), true, true);
JSONArray array = new JSONArray();
@@ -515,11 +549,11 @@
mAccount.accountFromAddresses = array.toString();
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, mAccount.name, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY, currentAccount.account,
- null, null);
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY, currentAccount.account,
+ EMPTY_ACCOUNT_LIST, null);
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY);
@@ -538,16 +572,16 @@
* Test the cases where:
* The user is replying to a message sent from one of their custom froms
*/
- public void testRecipientsRefMessageReplyAllCustomFrom() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefMessageReplyAllCustomFrom() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String customFrom = "CUSTOMaccount1@mockuiprovider.com";
refMessage.setFrom("senderaccount@mockuiprovider.com");
refMessage.setTo("someotheraccount@mockuiprovider.com, "
+ "someotheraccount2@mockuiprovider.com, someotheraccount4@mockuiprovider.com, "
+ customFrom);
- final ComposeActivity activity = mActivity;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom,
customFrom, customFrom, true, true);
JSONArray array = new JSONArray();
@@ -555,10 +589,10 @@
mAccount.accountFromAddresses = array.toString();
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, mAccount.name, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
- currentAccount.account, null, null);
- mActivity.runOnUiThread(new Runnable() {
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
+ currentAccount.account, EMPTY_ACCOUNT_LIST, null);
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -580,16 +614,16 @@
* Test the cases where:
* The user is replying to a message sent from one of their custom froms
*/
- public void testRecipientsRefMessageReplyAllCustomFromThisAccount() {
- setAccount("account1@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testRecipientsRefMessageReplyAllCustomFromThisAccount() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account1@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
final String customFrom = "CUSTOMaccount1@mockuiprovider.com";
refMessage.setFrom("account1@mockuiprovider.com");
refMessage.setTo("someotheraccount@mockuiprovider.com, "
+ "someotheraccount2@mockuiprovider.com, someotheraccount4@mockuiprovider.com, "
+ customFrom);
- final ComposeActivity activity = mActivity;
- mActivity.mFromSpinner = new FromAddressSpinner(mActivity);
+ activity.mFromSpinner = new FromAddressSpinner(activity);
ReplyFromAccount a = new ReplyFromAccount(mAccount, mAccount.uri, customFrom,
customFrom, customFrom, true, true);
JSONArray array = new JSONArray();
@@ -597,10 +631,10 @@
mAccount.accountFromAddresses = array.toString();
ReplyFromAccount currentAccount = new ReplyFromAccount(mAccount, mAccount.uri,
mAccount.name, mAccount.name, mAccount.name, true, false);
- mActivity.mFromSpinner.setCurrentAccount(currentAccount);
- mActivity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
- currentAccount.account, null, null);
- mActivity.runOnUiThread(new Runnable() {
+ activity.mFromSpinner.setCurrentAccount(currentAccount);
+ activity.mFromSpinner.initialize(ComposeActivity.REPLY_ALL,
+ currentAccount.account, EMPTY_ACCOUNT_LIST, null);
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.initReplyRecipients(refMessage, ComposeActivity.REPLY_ALL);
@@ -619,6 +653,153 @@
});
}
+ // Test replying to a message in the first account in the list, and verify that
+ // the Compose Activity's from account for the reply is correct
+ public void testReplySendingAccount0() throws Throwable {
+ final Context context = getInstrumentation().getContext();
+ // Get the test account
+ final Account currentAccount = getAccountForName(context, "account0@mockuiprovider.com");
+
+ // Get the message to be replied to
+ final Message refMessage =
+ getRefMessage(context.getContentResolver(), currentAccount.folderListUri);
+
+ // Create the reply intent
+ final Intent replyIntent =
+ ComposeActivity.updateActionIntent(currentAccount, refMessage.uri,
+ ComposeActivity.REPLY, new Intent());
+
+ setActivityIntent(replyIntent);
+
+ final ComposeActivity activity = getActivity();
+ final String refMessageFromAccount = refMessage.getFrom();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String[] to = activity.getToAddresses();
+ String[] cc = activity.getCcAddresses();
+ String[] bcc = activity.getBccAddresses();
+ Account fromAccount = activity.getFromAccount();
+ assertEquals(1, to.length);
+ assertEquals(refMessageFromAccount,
+ Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
+ assertEquals(0, cc.length);
+ assertEquals(0, bcc.length);
+ assertEquals("account0@mockuiprovider.com", fromAccount.name);
+ }
+ });
+ }
+
+ // Test replying to a message in the third account in the list, and verify that
+ // the Compose Activity's from account for the reply is correct
+ public void testReplySendingAccount1() throws Throwable {
+ final Context context = getInstrumentation().getContext();
+ // Get the test account
+ final Account currentAccount = getAccountForName(context, "account2@mockuiprovider.com");
+
+ // Get the message to be replied to
+ final Message refMessage =
+ getRefMessage(context.getContentResolver(), currentAccount.folderListUri);
+
+ // Create the reply intent
+ final Intent replyIntent =
+ ComposeActivity.updateActionIntent(currentAccount, refMessage.uri,
+ ComposeActivity.REPLY, new Intent());
+
+ setActivityIntent(replyIntent);
+
+ final ComposeActivity activity = getActivity();
+ Account fromAccount = activity.getFromAccount();
+
+ final String refMessageFromAccount = refMessage.getFrom();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String[] to = activity.getToAddresses();
+ String[] cc = activity.getCcAddresses();
+ String[] bcc = activity.getBccAddresses();
+ Account fromAccount = activity.getFromAccount();
+ assertEquals(1, to.length);
+ assertEquals(refMessageFromAccount,
+ Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
+ assertEquals(0, cc.length);
+ assertEquals(0, bcc.length);
+ assertEquals("account2@mockuiprovider.com", fromAccount.name);
+ }
+ });
+ }
+
+ // Test a mailto VIEW Intent, with an account specified
+ public void testMailToAccount() throws Throwable {
+ final Context context = getInstrumentation().getContext();
+ // Get the test account
+ final Account currentAccount = getAccountForName(context, "account2@mockuiprovider.com");
+
+ // Create the mailto intent
+ final Intent mailtoIntent =
+ new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:test@localhost.com"));
+ Utils.addAccountToMailtoIntent(mailtoIntent, currentAccount);
+
+ setActivityIntent(mailtoIntent);
+
+ final ComposeActivity activity = getActivity();
+ Account fromAccount = activity.getFromAccount();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String[] to = activity.getToAddresses();
+ String[] cc = activity.getCcAddresses();
+ String[] bcc = activity.getBccAddresses();
+ Account fromAccount = activity.getFromAccount();
+ assertEquals( 1, to.length);
+ assertEquals("test@localhost.com",
+ Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
+ assertEquals(0, cc.length);
+ assertEquals(0, bcc.length);
+ assertEquals("account2@mockuiprovider.com", fromAccount.name);
+ }
+ });
+ }
+
+ // Test a mailto VIEW Intent, with no account specified. The fromAccount should default to the
+ // last sent account.
+ public void testMailToAccountWithLastSentAccount() throws Throwable {
+ final Context context = getInstrumentation().getContext();
+
+ // Set the last sent account to account0
+ final Account lastSentAccount = getAccountForName(context, "account1@mockuiprovider.com");
+ MailAppProvider appProvider = MailAppProvider.getInstance();
+ appProvider.setLastSentFromAccount(lastSentAccount.uri.toString());
+
+ // Create the mailto intent
+ final Intent mailtoIntent =
+ new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:test@localhost.com"));
+
+ setActivityIntent(mailtoIntent);
+
+ final ComposeActivity activity = getActivity();
+ Account fromAccount = activity.getFromAccount();
+
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String[] to = activity.getToAddresses();
+ String[] cc = activity.getCcAddresses();
+ String[] bcc = activity.getBccAddresses();
+ Account fromAccount = activity.getFromAccount();
+ assertEquals( 1, to.length);
+ assertEquals("test@localhost.com",
+ Rfc822Tokenizer.tokenize(to[0])[0].getAddress());
+ assertEquals(0, cc.length);
+ assertEquals(0, bcc.length);
+ assertEquals("account1@mockuiprovider.com", fromAccount.name);
+ }
+ });
+ }
+
private static String createAttachmentsJson() {
Attachment attachment1 = new Attachment();
attachment1.contentUri = Uri.parse("www.google.com");
@@ -639,14 +820,14 @@
}
// First test: switch reply to reply all to fwd, 1 to recipient, 1 cc recipient.
- public void testChangeModes0() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testChangeModes0() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("fromaccount@mockuiprovider.com");
refMessage.setTo("account0@mockuiprovider.com");
refMessage.setCc("ccaccount@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.mRefMessage = refMessage;
@@ -673,14 +854,14 @@
}
// Switch reply to reply all to fwd, 2 to recipients, 1 cc recipient.
- public void testChangeModes1() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testChangeModes1() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("fromaccount@mockuiprovider.com");
refMessage.setTo("account0@mockuiprovider.com, toaccount0@mockuiprovider.com");
refMessage.setCc("ccaccount@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.mRefMessage = refMessage;
@@ -700,7 +881,7 @@
|| activity.getCcAddresses()[1].contains(refMessage.getCc()));
assertTrue(activity.getCcAddresses()[0].contains("toaccount0@mockuiprovider.com")
|| activity.getCcAddresses()[1]
- .contains("toaccount0@mockuiprovider.com"));
+ .contains("toaccount0@mockuiprovider.com"));
assertEquals(activity.getBccAddresses().length, 0);
activity.onNavigationItemSelected(2, ComposeActivity.FORWARD);
assertEquals(activity.getToAddresses().length, 0);
@@ -711,14 +892,14 @@
}
// Switch reply to reply all to fwd, 2 to recipients, 2 cc recipients.
- public void testChangeModes2() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testChangeModes2() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.setFrom("fromaccount@mockuiprovider.com");
refMessage.setTo("account0@mockuiprovider.com, toaccount0@mockuiprovider.com");
refMessage.setCc("ccaccount@mockuiprovider.com, ccaccount2@mockuiprovider.com");
- final ComposeActivity activity = mActivity;
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.mRefMessage = refMessage;
@@ -745,9 +926,9 @@
|| activity.getCcAddresses()[2].contains("toaccount0@mockuiprovider.com"));
assertTrue(activity.getCcAddresses()[0].contains("toaccount0@mockuiprovider.com")
|| activity.getCcAddresses()[1]
- .contains("toaccount0@mockuiprovider.com")
+ .contains("toaccount0@mockuiprovider.com")
|| activity.getCcAddresses()[2]
- .contains("toaccount0@mockuiprovider.com"));
+ .contains("toaccount0@mockuiprovider.com"));
assertEquals(activity.getBccAddresses().length, 0);
activity.onNavigationItemSelected(2, ComposeActivity.FORWARD);
assertEquals(activity.getToAddresses().length, 0);
@@ -758,13 +939,13 @@
}
// Switch reply to reply all to fwd, 2 attachments.
- public void testChangeModes3() {
- setAccount("account0@mockuiprovider.com");
- final Message refMessage = getRefMessage();
+ public void testChangeModes3() throws Throwable {
+ final ComposeActivity activity = getActivity();
+ setAccount(activity, "account0@mockuiprovider.com");
+ final Message refMessage = getRefMessage(activity.getContentResolver());
refMessage.hasAttachments = true;
refMessage.attachmentsJson = createAttachmentsJson();
- final ComposeActivity activity = mActivity;
- mActivity.runOnUiThread(new Runnable() {
+ runTestOnUiThread(new Runnable() {
@Override
public void run() {
activity.mRefMessage = refMessage;