Merge "Fix bug where constructing message attachment uri with null/empty partId will remove the trailing backslash, causing the uri to not match the expected pattern." into jb-ub-mail-ur9
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ff40c23..24fa2b2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -143,12 +143,6 @@
         <provider android:name="com.android.mail.providers.SuggestionsProvider"
             android:authorities="com.android.mail.suggestionsprovider" />
 
-        <receiver android:name=".providers.protos.boot.AccountReceiver">
-          <intent-filter>
-              <action android:name="com.android.mail.providers.protos.boot.intent.ACTION_PROVIDER_CREATED" />
-          </intent-filter>
-        </receiver>
-
         <service android:name=".compose.EmptyService"/>
 
         <!-- Widget -->
diff --git a/assets/script.js b/assets/script.js
index c4f3ae6..51a9d69 100644
--- a/assets/script.js
+++ b/assets/script.js
@@ -28,7 +28,9 @@
  * to shrink by this much. Expressed as a ratio of:
  * (original width difference : width difference after transforms);
  */
-TRANSFORM_MINIMUM_EFFECTIVE_RATIO = 0.75;
+TRANSFORM_MINIMUM_EFFECTIVE_RATIO = 0.7;
+
+var gTransformText = {};
 
 /**
  * Returns the page offset of an element.
@@ -182,9 +184,7 @@
             el.style.zoom = 1;
         }
         newZoom = documentWidth / el.scrollWidth;
-        if (ENABLE_MUNGE_TABLES) {
-            mungeTables(el, documentWidth, el.scrollWidth);
-        }
+        transformContent(el, documentWidth, el.scrollWidth);
         newZoom = documentWidth / el.scrollWidth;
         if (NORMALIZE_MESSAGE_WIDTHS) {
             el.style.zoom = newZoom;
@@ -192,97 +192,141 @@
     }
 }
 
-function mungeTables(el, docWidth, elWidth) {
+function transformContent(el, docWidth, elWidth) {
     var nodes;
     var i, len;
+    var index;
     var newWidth = elWidth;
     var wStr;
     var touched;
+    // the format of entries in this array is:
+    // entry := [ undoFunction, undoFunctionThis, undoFunctionParamArray ]
     var actionLog = [];
     var node;
+    var done = false;
+    var msgId;
+    var transformText;
+    var existingText;
+    var textElement;
     var start;
     if (elWidth <= docWidth) {
         return;
     }
 
     start = Date.now();
-    // Try munging all divs with inline styles where the width
+
+    if (el.parentElement.classList.contains("mail-message")) {
+        msgId = el.parentElement.id;
+        transformText = "[origW=" + elWidth + "/" + docWidth;
+    }
+
+    // Try munging all divs or textareas with inline styles where the width
     // is wider than docWidth, and change it to be a max-width.
     touched = false;
-    nodes = el.querySelectorAll("div[style]");
-    for (i = 0, len = nodes.length; i < len; i++) {
-        node = nodes[i];
-        wStr = node.style.width;
-        if (wStr && wStr.slice(0, -2) > docWidth) {
-            node.style.width = "";
-            node.style.maxWidth = wStr;
-            touched = true;
-        }
-    }
+    nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("div[style], textarea[style]") : [];
+    touched = transformBlockElements(nodes, docWidth, actionLog);
     if (touched) {
         newWidth = el.scrollWidth;
         console.log("ran div-width munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
             + " docW=" + docWidth);
+        if (msgId) {
+            transformText += " DIV:newW=" + newWidth;
+        }
         if (newWidth <= docWidth) {
-            console.log("munger succeeded, elapsed time=" + (Date.now() - start));
-            return;
+            done = true;
         }
     }
 
-    // OK, that wasn't enough. Find tables with widths and override their widths.
-    touched = addClassToElements(el.querySelectorAll("table"), shouldMungeTable, "munged",
-        actionLog);
-    if (touched) {
-        newWidth = el.scrollWidth;
-        console.log("ran table munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
-            + " docW=" + docWidth);
-        if (newWidth <= docWidth) {
-            console.log("munger succeeded, elapsed time=" + (Date.now() - start));
-            return;
+    if (!done) {
+        // OK, that wasn't enough. Find images with widths and override their widths.
+        nodes = ENABLE_MUNGE_IMAGES ? el.querySelectorAll("img") : [];
+        touched = transformImages(nodes, docWidth, actionLog);
+        if (touched) {
+            newWidth = el.scrollWidth;
+            console.log("ran img munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+                + " docW=" + docWidth);
+            if (msgId) {
+                transformText += " IMG:newW=" + newWidth;
+            }
+            if (newWidth <= docWidth) {
+                done = true;
+            }
         }
     }
 
-    // OK, that wasn't enough. Try munging all <td> to override any width and nowrap set.
-    touched = addClassToElements(el.querySelectorAll("td"), null /* mungeAll */, "munged",
-        actionLog);
-    if (touched) {
-        newWidth = el.scrollWidth;
-        console.log("ran td munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
-            + " docW=" + docWidth);
-        if (newWidth <= docWidth) {
-            console.log("munger succeeded, elapsed time=" + (Date.now() - start));
-            return;
+    if (!done) {
+        // OK, that wasn't enough. Find tables with widths and override their widths.
+        nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("table") : [];
+        touched = addClassToElements(nodes, shouldMungeTable, "munged",
+            actionLog);
+        if (touched) {
+            newWidth = el.scrollWidth;
+            console.log("ran table munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+                + " docW=" + docWidth);
+            if (msgId) {
+                transformText += " TABLE:newW=" + newWidth;
+            }
+            if (newWidth <= docWidth) {
+                done = true;
+            }
         }
     }
 
-    // OK, that wasn't enough. Try further munging all <td> to override text wrapping.
-    touched = addClassToElements(el.querySelectorAll("td"), null /* mungeAll */, "munged2",
-        actionLog);
-    if (touched) {
-        newWidth = el.scrollWidth;
-        console.log("ran td munger2 on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
-            + " docW=" + docWidth);
-        if (newWidth <= docWidth) {
-            console.log("munger succeeded, elapsed time=" + (Date.now() - start));
-            return;
+    if (!done) {
+        // OK, that wasn't enough. Try munging all <td> to override any width and nowrap set.
+        nodes = ENABLE_MUNGE_TABLES ? el.querySelectorAll("td") : [];
+        touched = addClassToElements(nodes, null /* mungeAll */, "munged",
+            actionLog);
+        if (touched) {
+            newWidth = el.scrollWidth;
+            console.log("ran td munger on el=" + el + " oldW=" + elWidth + " newW=" + newWidth
+                + " docW=" + docWidth);
+            if (msgId) {
+                transformText += " TD:newW=" + newWidth;
+            }
+            if (newWidth <= docWidth) {
+                done = true;
+            }
         }
     }
 
     // If the transformations shrank the width significantly enough, leave them in place.
     // We figure that in those cases, the benefits outweight the risk of rendering artifacts.
-    //
-    // TODO: this is a risky transform that should not be attempted on sufficiently complex mail.
-    // (TBD how to measure that)
-    if ((elWidth - newWidth) / (elWidth - docWidth) > TRANSFORM_MINIMUM_EFFECTIVE_RATIO) {
-        console.log("transform(s) deemed effective enough. elapsed time="
-            + (Date.now() - start));
+    if (!done && (elWidth - newWidth) / (elWidth - docWidth) >
+            TRANSFORM_MINIMUM_EFFECTIVE_RATIO) {
+        console.log("transform(s) deemed effective enough");
+        done = true;
+    }
+
+    if (done) {
+        if (msgId) {
+            transformText += "]";
+            existingText = gTransformText[msgId];
+            if (!existingText) {
+                transformText = "Message transforms: " + transformText;
+            } else {
+                transformText = existingText + " " + transformText;
+            }
+            gTransformText[msgId] = transformText;
+            window.mail.onMessageTransform(msgId, transformText);
+            textElement = el.firstChild;
+            if (!textElement.classList || !textElement.classList.contains("transform-text")) {
+                textElement = document.createElement("div");
+                textElement.classList.add("transform-text");
+                textElement.style.fontSize = "10px";
+                textElement.style.color = "#ccc";
+                el.insertBefore(textElement, el.firstChild);
+            }
+            textElement.innerHTML = transformText + "<br>";
+        }
+        console.log("munger(s) succeeded, elapsed time=" + (Date.now() - start));
         return;
     }
 
     // reverse all changes if the width is STILL not narrow enough
     // (except the width->maxWidth change, which is not particularly destructive)
     for (i = 0, len = actionLog.length; i < len; i++) {
-        actionLog[i][0].classList.remove(actionLog[i][1]);
+        actionLog[i][0].apply(actionLog[i][1], actionLog[i][2]);
     }
     if (actionLog.length > 0) {
         console.log("all mungers failed, changes reversed. elapsed time=" + (Date.now() - start));
@@ -296,14 +340,75 @@
     for (i = 0, len = nodes.length; i < len; i++) {
         node = nodes[i];
         if (!conditionFn || conditionFn(node)) {
+            if (node.classList.contains(classToAdd)) {
+                continue;
+            }
             node.classList.add(classToAdd);
             added = true;
-            actionLog.push([node, classToAdd]);
+            actionLog.push([node.classList.remove, node.classList, [classToAdd]]);
         }
     }
     return added;
 }
 
+function transformBlockElements(nodes, docWidth, actionLog) {
+    var i, len;
+    var node;
+    var wStr;
+    var index;
+    var touched = false;
+
+    for (i = 0, len = nodes.length; i < len; i++) {
+        node = nodes[i];
+        wStr = node.style.width || node.style.minWidth;
+        index = wStr ? wStr.indexOf("px") : -1;
+        if (index >= 0 && wStr.slice(0, index) > docWidth) {
+            saveStyleProperty(node, "width", actionLog);
+            saveStyleProperty(node, "minWidth", actionLog);
+            saveStyleProperty(node, "maxWidth", actionLog);
+            node.style.width = "100%";
+            node.style.minWidth = "";
+            node.style.maxWidth = wStr;
+            touched = true;
+        }
+    }
+    return touched;
+}
+
+function transformImages(nodes, docWidth, actionLog) {
+    var i, len;
+    var node;
+    var w, h;
+    var touched = false;
+
+    for (i = 0, len = nodes.length; i < len; i++) {
+        node = nodes[i];
+        w = node.offsetWidth;
+        h = node.offsetHeight;
+        // shrink w/h proportionally if the img is wider than available width
+        if (w > docWidth) {
+            saveStyleProperty(node, "maxWidth", actionLog);
+            saveStyleProperty(node, "width", actionLog);
+            saveStyleProperty(node, "height", actionLog);
+            node.style.maxWidth = docWidth + "px";
+            node.style.width = "100%";
+            node.style.height = "auto";
+            touched = true;
+        }
+    }
+    return touched;
+}
+
+function saveStyleProperty(node, property, actionLog) {
+    var savedName = "data-" + property;
+    node.setAttribute(savedName, node.style[property]);
+    actionLog.push([undoSetProperty, node, [property, savedName]]);
+}
+
+function undoSetProperty(property, savedProperty) {
+    this.style[property] = savedProperty ? this.getAttribute(savedProperty) : "";
+}
+
 function shouldMungeTable(table) {
     return table.hasAttribute("width") || table.style.width;
 }
diff --git a/res/layout-sw600dp/account_switch_spinner_item.xml b/res/layout-sw600dp/account_switch_spinner_item.xml
deleted file mode 100644
index c6ee7c1..0000000
--- a/res/layout-sw600dp/account_switch_spinner_item.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2011 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.
--->
-
-<!-- View shown in the navigation spinner in the actionbar.  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:paddingLeft="0dip"
-    android:layout_marginLeft="0dip"
-    android:layout_width="match_parent">
-
-    <LinearLayout
-        android:layout_height="match_parent"
-        android:id="@+id/account_spinner_container"
-        android:orientation="vertical"
-        android:gravity="center_vertical"
-        android:background="@drawable/spinner_ab_holo_light"
-        android:duplicateParentState="false"
-        android:layout_alignParentLeft="true"
-        android:focusable="true"
-        android:focusableInTouchMode="false"
-        style="@style/AccountSpinnerStyle">
-        <TextView
-            android:id="@+id/account_first"
-            style="@style/AccountSpinnerAnchorTextPrimary"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:includeFontPadding="false"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-        <TextView
-            android:id="@+id/account_second"
-            style="@style/AccountSpinnerAnchorTextSecondary"
-            android:singleLine="true"
-            android:ellipsize="end"
-            android:includeFontPadding="false"
-            android:layout_marginRight="4dp"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-    </LinearLayout>
-
-    <TextView
-        android:id="@+id/account_unread"
-        android:layout_toRightOf="@id/account_spinner_container"
-        style="@style/unreadCountActionBarTablet"/>
-</RelativeLayout>
diff --git a/res/layout/account_switch_spinner_item.xml b/res/layout/account_switch_spinner_item.xml
deleted file mode 100644
index 7681665..0000000
--- a/res/layout/account_switch_spinner_item.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2011 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.
--->
-
-<!-- View shown in the navigation spinner in the actionbar.  -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:paddingLeft="0dip"
-    android:layout_marginLeft="0dip"
-    android:layout_width="match_parent">
-
-    <!-- Place the unread count first, taking all the space it needs
-         to fit its content -->
-    <TextView
-        android:id="@+id/account_unread"
-        android:layout_alignParentRight="true"
-        android:layout_width="wrap_content"
-        android:layout_marginLeft="4dp"
-        style="@style/UnreadCountActionBar"/>
-
-    <!-- Container to soak up space and ensure that the caret attaches
-         to a short label name. This container should be anonymous because nothing
-         should reference it.
-         Phone only: On tablets, the width of the spinner is a constant for each
-         orientation. -->
-    <LinearLayout
-        android:layout_height="match_parent"
-        android:orientation="horizontal"
-        android:layout_width="fill_parent"
-        android:gravity="center_vertical"
-        android:clickable="false"
-        android:focusable="false"
-        android:layout_toLeftOf="@id/account_unread">
-
-        <!-- In the container, the label name takes up as much space
-             as it needs to show its content: this is to ensure that the
-             dropdown caret is flush with the label name. -->
-        <LinearLayout
-            android:layout_height="match_parent"
-            android:id="@+id/account_spinner_container"
-            android:orientation="vertical"
-            android:gravity="center_vertical"
-            android:background="@drawable/spinner_ab_holo_light"
-            android:focusable="true"
-            android:focusableInTouchMode="false"
-            style="@style/AccountSpinnerStyle">
-            <TextView
-                android:id="@+id/account_first"
-                style="@style/AccountSpinnerAnchorTextPrimary"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:includeFontPadding="false"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-            <TextView
-                android:id="@+id/account_second"
-                style="@style/AccountSpinnerAnchorTextSecondary"
-                android:singleLine="true"
-                android:ellipsize="end"
-                android:includeFontPadding="false"
-                android:layout_marginRight="4dp"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
-    </LinearLayout>
-</RelativeLayout>
diff --git a/res/layout/actionbar_view.xml b/res/layout/actionbar_view.xml
index ffb6c64..7d4b792 100644
--- a/res/layout/actionbar_view.xml
+++ b/res/layout/actionbar_view.xml
@@ -21,16 +21,10 @@
     label, and subject).
 -->
 <com.android.mail.ui.MailActionBarView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
+    android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:orientation="horizontal" >
-
-    <com.android.mail.ui.MailSpinner
-        android:id="@+id/account_spinner"
-        android:layout_height="match_parent"
-        style="@style/AccountSwitchSpinnerItem"
-        android:clickable="true"/>
-
+    <!-- Only used for displaying a subject view -->
     <include layout="@layout/actionbar_subject" />
 
 </com.android.mail.ui.MailActionBarView>
diff --git a/res/layout/folder_expand_item.xml b/res/layout/folder_expand_item.xml
new file mode 100644
index 0000000..5041582
--- /dev/null
+++ b/res/layout/folder_expand_item.xml
@@ -0,0 +1,55 @@
+<?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.
+-->
+
+<!-- This is a button for expanding/collapsing emails in FLF  -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/folder_expand_item"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical">
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/message_details_header_bottom_border_height"
+        android:visibility="visible"
+        android:background="@color/conv_subject_border" />
+
+    <TextView
+        android:id="@+id/folder_expand_text"
+        android:layout_width="match_parent"
+        android:layout_height="48dip"
+        android:layout_marginLeft="@dimen/folder_list_item_left_margin"
+        android:gravity="center_vertical"
+        android:ellipsize="end"
+        android:singleLine="true"
+        android:textAllCaps="true"
+        android:textColor="@color/folder_list_heading_text_color"/>
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/message_details_header_bottom_border_height"
+        android:visibility="visible"
+        android:background="@color/conv_subject_border" />
+
+    <ImageView
+        android:layout_gravity="top|right"
+        android:layout_marginTop="14dip"
+        android:layout_marginRight="14dip"
+        android:id="@+id/details_expander"
+        style="@style/MessageHeaderExpanderMinimizedStyle" />
+</FrameLayout>
diff --git a/res/layout/search_actionbar_view.xml b/res/layout/search_actionbar_view.xml
index 93d8de8..613d8c4 100644
--- a/res/layout/search_actionbar_view.xml
+++ b/res/layout/search_actionbar_view.xml
@@ -26,15 +26,6 @@
     android:layout_height="match_parent"
     android:orientation="horizontal" >
 
-    <com.android.mail.ui.MailSpinner
-        android:id="@+id/account_spinner"
-        android:layout_height="match_parent"
-        android:layout_width="wrap_content"
-        style="@style/PlainSpinnerDropdown"
-        android:focusableInTouchMode="false"
-        android:focusable="false"
-        android:clickable="true"/>
-
     <include layout="@layout/actionbar_subject" />
 
 </com.android.mail.ui.SearchMailActionBarView>
\ No newline at end of file
diff --git a/res/layout/secure_conversation_view.xml b/res/layout/secure_conversation_view.xml
index 56679f2..da1dae3 100644
--- a/res/layout/secure_conversation_view.xml
+++ b/res/layout/secure_conversation_view.xml
@@ -26,21 +26,16 @@
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:orientation="vertical">
-            <RelativeLayout android:id="@+id/header"
+            <include layout="@layout/conversation_view_header"
+                android:id="@+id/conv_header"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" />
+
+            <include layout="@layout/conversation_message_header"
+                android:id="@+id/message_header"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:background="@android:color/white">
-                <include layout="@layout/conversation_view_header"
-                    android:id="@+id/conv_header"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content" />
-
-                <include layout="@layout/conversation_message_header"
-                    android:id="@+id/message_header"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_below="@id/conv_header" />
-            </RelativeLayout>
+                android:layout_below="@id/conv_header" />
             <!-- base WebView layer -->
             <WebView
                 android:id="@+id/webview"
@@ -54,12 +49,6 @@
                 android:visibility="gone" />
         </LinearLayout>
     </ScrollView>
-    <FrameLayout
-            android:id="@+id/conversation_topmost_overlay"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent">
-            <!-- TODO: scroll indicators go HERE on top of all other layers -->
-    </FrameLayout>
 
     <include layout="@layout/conversation_load_spinner"/>
 
diff --git a/res/menu-sw600dp-port/conversation_list_search_results_actions.xml b/res/menu-sw600dp-port/conversation_list_search_results_actions.xml
index 357ba1b..ba722e6 100644
--- a/res/menu-sw600dp-port/conversation_list_search_results_actions.xml
+++ b/res/menu-sw600dp-port/conversation_list_search_results_actions.xml
@@ -35,11 +35,6 @@
         android:icon="@drawable/ic_menu_refresh_holo_light"
         android:alphabeticShortcut="@string/trigger_refresh_char" />
 
-    <!-- Available for Folders with SUPPORTS_SETTINGS capability -->
-    <item android:id="@+id/folder_options"
-        android:title="@string/menu_folder_options"
-        android:showAsAction="never"  />
-
     <item android:id="@+id/settings"
         android:title="@string/menu_settings"
         android:showAsAction="never" />
diff --git a/res/menu-sw600dp-port/conversation_search_results_actions.xml b/res/menu-sw600dp-port/conversation_search_results_actions.xml
index ca13500..e228059 100644
--- a/res/menu-sw600dp-port/conversation_search_results_actions.xml
+++ b/res/menu-sw600dp-port/conversation_search_results_actions.xml
@@ -51,11 +51,6 @@
         android:title="@string/report_spam"
         android:showAsAction="never"/>
 
-    <!-- Available for Folders with SUPPORTS_SETTINGS capability -->
-    <item android:id="@+id/folder_options"
-        android:title="@string/menu_folder_options"
-        android:showAsAction="never"  />
-
     <item android:id="@+id/settings"
         android:title="@string/menu_settings"
         android:showAsAction="never" />
@@ -72,4 +67,4 @@
         android:icon="@android:drawable/ic_menu_help"
         android:title="@string/help_and_info" />
 
-</menu>
\ No newline at end of file
+</menu>
diff --git a/res/menu/conversation_list_menu.xml b/res/menu/conversation_list_menu.xml
index 589097a..76ae716 100644
--- a/res/menu/conversation_list_menu.xml
+++ b/res/menu/conversation_list_menu.xml
@@ -34,7 +34,7 @@
     <!-- Always available -->
     <item android:id="@+id/show_all_folders"
         android:title="@string/show_all_folders"
-        android:showAsAction="ifRoom"
+        android:showAsAction="never"
         android:icon="@drawable/ic_menu_folders_holo_light" />
 
     <!-- Always available -->
diff --git a/res/menu/message_header_overflow_menu.xml b/res/menu/message_header_overflow_menu.xml
index e3e9f0b..035eca2 100644
--- a/res/menu/message_header_overflow_menu.xml
+++ b/res/menu/message_header_overflow_menu.xml
@@ -26,4 +26,10 @@
     <item android:id="@+id/forward"
           android:icon="@drawable/ic_forward_holo_dark"
           android:title="@string/forward" />
+    <item android:id="@+id/report_rendering_problem"
+          android:icon="@drawable/ic_forward_holo_dark"
+          android:title="@string/report_rendering_problem" />
+    <item android:id="@+id/report_rendering_improvement"
+          android:icon="@drawable/ic_forward_holo_dark"
+          android:title="@string/report_rendering_improvement" />
 </menu>
diff --git a/res/raw/template_conversation_lower.html b/res/raw/template_conversation_lower.html
index bbcbd4f..b128077 100644
--- a/res/raw/template_conversation_lower.html
+++ b/res/raw/template_conversation_lower.html
@@ -10,6 +10,7 @@
   var ENABLE_CONTENT_READY = %s;
   var NORMALIZE_MESSAGE_WIDTHS = %s;
   var ENABLE_MUNGE_TABLES = %s;
+  var ENABLE_MUNGE_IMAGES = %s;
 </script>
 <script type="text/javascript" src="file:///android_asset/script.js"></script>
 </html>
diff --git a/res/raw/template_conversation_upper.html b/res/raw/template_conversation_upper.html
index 1b3ecce..6222762 100644
--- a/res/raw/template_conversation_upper.html
+++ b/res/raw/template_conversation_upper.html
@@ -21,6 +21,12 @@
     body {
         font-size: 80%%;
     }
+    blockquote {
+        margin-left: 0.8ex !important;
+        margin-right: 0 !important;
+        border-left:1px #ccc solid !important;
+        padding-left: 1ex !important;
+    }
     table.munged {
         width: auto !important;
     }
@@ -28,10 +34,6 @@
         width: auto !important;
         white-space: normal !important;
     }
-    td.munged2 {
-        word-break: break-all !important;
-        word-wrap: break-word !important;
-    }
     .initial-load {
         /* 0x0 and 1x1 may be short-circuited by WebView */
         width: 2px;
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index fd7c593..e2e55c0 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Skuif na"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Vouerinstellings"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Vouers"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinkroniseer en stel in kennis"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Vouerinstellings"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Rekeninginstellings"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Het vouer verander."</item>
     <item quantity="other" msgid="8918589141287976985">"Het vouers verander."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultate"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Search word nie ondersteun op hierdie rekening nie."</string>
     <string name="searchMode" msgid="3329807422114758583">"Soekmodus"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index aea32ca..5b832d4 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"አንቀሳቅስ ወደ"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"የአቃፊ ቅንብሮች"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"አቃፊዎች"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"አመሳስልና አሳውቅ"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"የአቃፊ ቅንብሮች"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"የመለያ ቅንብሮች"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"የተቀየረ አቃፊ። የተለወጠ አቃፊ።"</item>
     <item quantity="other" msgid="8918589141287976985">"የተቀየሩ አቃፊዎች።"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"ውጤቶች"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"ፍለጋ በዚህ መለያ አይደገፍም።"</string>
     <string name="searchMode" msgid="3329807422114758583">"የፍለጋ ሁናቴ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 9b38a60..cd7f37c 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"نقل إلى"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"إعدادات المجلدات"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"المجلدات"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"المزامنة والإشعارات"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"إعدادات المجلد"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"إعدادات الحساب"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"تم تغيير المجلد."</item>
     <item quantity="other" msgid="8918589141287976985">"تم تغيير المجلدات."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"النتائج"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"لا يمكن استخدام البحث على هذا الحساب."</string>
     <string name="searchMode" msgid="3329807422114758583">"وضع البحث"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 9b4a7cc..d119d6c 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Перанесці ў"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Налады тэчкi"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Тэчкі"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Сінхранізацыя і апавяшчэнне"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Налады тэчак"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Налады ўліковага запісу"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Змененая тэчка."</item>
     <item quantity="other" msgid="8918589141287976985">"Змененыя тэчкі."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Вынікі"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"У гэтым уліковым запісе пошук не падтрымліваецца."</string>
     <string name="searchMode" msgid="3329807422114758583">"Рэжым пошуку"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 9bfa480..f35f63d 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Преместване във:"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Настройки за папките"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Папки"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Синхронизиране и известяване"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Настройки за папката"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Настройки на профила"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Променихте папката."</item>
     <item quantity="other" msgid="8918589141287976985">"Променихте папките."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Резултати"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Търсенето не се поддържа за този профил."</string>
     <string name="searchMode" msgid="3329807422114758583">"Режим на търсене"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 216eaea..8b30f07 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mou a"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Configuració de la carpeta"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Carpetes"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronitza i notifica"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Configuració de la carpeta"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Configuració del compte"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"S\'ha canviat la carpeta."</item>
     <item quantity="other" msgid="8918589141287976985">"S\'han canviat les carpetes."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultats"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"La cerca no és compatible en aquest compte."</string>
     <string name="searchMode" msgid="3329807422114758583">"Mode de cerca"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index dfc28cb..487aaad 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Přesunout do"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Nastavení složek"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Složky"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchronizace a upozornění"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Nastavení složek"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Nastavení účtu"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Složka změněna."</item>
     <item quantity="other" msgid="8918589141287976985">"Složky změněny."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Výsledky"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Vyhledávání není v tomto účtu podporováno."</string>
     <string name="searchMode" msgid="3329807422114758583">"Režim vyhledávání"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index b1d97d9..ae7c73a 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Flyt til"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Indstillinger for mapper"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mapper"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synkroniser og underret"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Indstillinger for mapper"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Kontoindstillinger"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Ændret mappe."</item>
     <item quantity="other" msgid="8918589141287976985">"Ændrede mapper."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultater"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Søgningen understøttes ikke på denne konto."</string>
     <string name="searchMode" msgid="3329807422114758583">"Søgetilstand"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 4008169..2ca30c3 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Verschieben nach"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Ordnereinstellungen"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Ordner"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchron. &amp;  benachrichtigen"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Ordnereinstellungen"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Kontoeinstellungen"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Ordner geändert"</item>
     <item quantity="other" msgid="8918589141287976985">"Ordner geändert"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Ergebnisse"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Die Suche wird für dieses Konto nicht unterstützt."</string>
     <string name="searchMode" msgid="3329807422114758583">"Suchmodus"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 24550d9..59f1748 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Μετακίνηση σε"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Ρυθμίσεις φακέλων"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Φάκελοι"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Συγχρονισμός και ειδοποίηση"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Ρυθμίσεις φακέλου..."</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Ρυθμίσεις Λογαριασμού"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Αλλαγή φακέλου."</item>
     <item quantity="other" msgid="8918589141287976985">"Αλλαγή φακέλων."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Αποτελέσματα"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Η αναζήτηση δεν υποστηρίζεται σε αυτόν τον λογαριασμό."</string>
     <string name="searchMode" msgid="3329807422114758583">"Λειτουργία αναζήτησης"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 8a81e56..b3e54f6 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Move to"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Folder settings"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Folders"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sync &amp; notify"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Folder settings"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Account settings"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Changed folder."</item>
     <item quantity="other" msgid="8918589141287976985">"Changed folders."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Results"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Search is not supported on this account."</string>
     <string name="searchMode" msgid="3329807422114758583">"Search Mode"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 41f0092..3a845c4 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mover a"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Configuración de carpetas"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Carpetas"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizar y notificar"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Configuración de la carpeta"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Configuración de la cuenta"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Carpeta modificada"</item>
     <item quantity="other" msgid="8918589141287976985">"Carpetas modificadas"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultados"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Esta cuenta no admite la función de búsqueda."</string>
     <string name="searchMode" msgid="3329807422114758583">"Buscar modo"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index cdc4a42..f6f692c 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mover a"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Ajustes de carpeta"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Carpetas"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizar y notificar"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Ajustes de carpeta"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Ajustes de cuenta"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Carpeta cambiada"</item>
     <item quantity="other" msgid="8918589141287976985">"Carpetas cambiadas"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultados"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Esta cuenta no admite la función de búsqueda."</string>
     <string name="searchMode" msgid="3329807422114758583">"Modo de búsqueda"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 250d094..857e31f 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Teisalda asukohta"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Kausta seaded"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Kaustad"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sünkroonimine ja teavitamine"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Kausta seaded"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Konto seaded"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Muudetud kaust."</item>
     <item quantity="other" msgid="8918589141287976985">"Muudetud kaustad."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Tulemused"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Sellel kontol ei toetata otsingut."</string>
     <string name="searchMode" msgid="3329807422114758583">"Otsimisrežiim"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 83b8a52..444a3c4 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"انتقال به"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"تنظیمات پوشه"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"پوشه‌ها"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"همگام‌سازی و اعلان"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"تنظیمات پوشه"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"تنظیمات حساب"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"پوشه تغییر کرد."</item>
     <item quantity="other" msgid="8918589141287976985">"پوشه‌ها تغییر کردند."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"نتایج"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"جستجو در این حساب پشتیبانی نمی‌شود."</string>
     <string name="searchMode" msgid="3329807422114758583">"حالت جستجو"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index b8bc436..994a196 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Siirrä kansioon"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Kansion asetukset"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Kansiot"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synkronoi ja ilmoita"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Kansion asetukset..."</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Tilin asetukset"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Kansiota muutettu."</item>
     <item quantity="other" msgid="8918589141287976985">"Kansioita muutettu."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Tulokset"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Hakua ei voi käyttää tällä tilillä."</string>
     <string name="searchMode" msgid="3329807422114758583">"Hakutapa"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 684cfa5..f1a7e0f 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Déplacer vers"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Paramètres des dossiers"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Dossiers"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchroniser et signaler"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Paramètres du dossier"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Paramètres de compte"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Dossier modifié."</item>
     <item quantity="other" msgid="8918589141287976985">"Dossiers modifiés."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Résultats"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"La fonctionnalité de recherche n\'est pas compatible avec ce compte."</string>
     <string name="searchMode" msgid="3329807422114758583">"Mode Recherche"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 23f6cc3..b1f8f3d 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"इसमें ले जाएं"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"फ़ोल्डर सेटिंग"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"फ़ोल्डर"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"समन्वयित करें और सूचित करें"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"फ़ोल्डर सेटिंग"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"खाता सेटिंग"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"फ़ोल्‍डर बदला गया."</item>
     <item quantity="other" msgid="8918589141287976985">"फ़ोल्डर बदले गए."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"परिणाम"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"इस खाते पर खोज समर्थित नहीं है."</string>
     <string name="searchMode" msgid="3329807422114758583">"खोज मोड"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 403c498..ea7f309 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Premjesti u/na"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Postavke mapa"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mape"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinkroniziraj i obavijesti"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Postavke mape"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Postavke računa"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Promijenjena mapa."</item>
     <item quantity="other" msgid="8918589141287976985">"Promijenjene mape."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Rezultati"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Pretraživanje nije podržano na ovom računu."</string>
     <string name="searchMode" msgid="3329807422114758583">"Način pretraživanja"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 81223dc..e1f12a9 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Áthelyezés ide:"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mappabeállítások"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mappák"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Szinkronizálás és értesítés"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mappabeállítások"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Fiókbeállítások"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"A mappa módosult."</item>
     <item quantity="other" msgid="8918589141287976985">"A mappák módosultak."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Találatok"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"A keresés nem támogatott ebben a fiókban."</string>
     <string name="searchMode" msgid="3329807422114758583">"Keresési mód"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 12497f5..50d0352 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Pindahkan ke"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Setelan folder"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Folder"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinkronkan &amp; beri tahu"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Setelan folder"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Pengaturan akun"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Folder diubah."</item>
     <item quantity="other" msgid="8918589141287976985">"Folder diubah."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Hasil"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Penelusuran tidak didukung pada akun ini."</string>
     <string name="searchMode" msgid="3329807422114758583">"Mode Penelusuran"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index f3281b0..2e17b51 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Sposta in"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Impostazioni cartella"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Cartelle"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizza e notifica"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Impostazioni cartella"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Impostazioni account"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Cartella cambiata."</item>
     <item quantity="other" msgid="8918589141287976985">"Cartelle cambiate."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Risultati"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"La ricerca non è supportata per l\'account in uso."</string>
     <string name="searchMode" msgid="3329807422114758583">"Modalità di ricerca"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a2ad658..dd9dd84 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"העבר אל"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"הגדרות תיקיה"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"תיקיות"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"סנכרן ושלח התראה"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"הגדרות תיקיה"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"הגדרות חשבון"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"התיקיה שונתה."</item>
     <item quantity="other" msgid="8918589141287976985">"התיקיות שונו."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"תוצאות"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"חיפוש אינו נתמך בחשבון זה."</string>
     <string name="searchMode" msgid="3329807422114758583">"מצב חיפוש"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index f7faa86..6bb7191 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"移動"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"フォルダの設定"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"フォルダ"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"同期と通知"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"フォルダの設定"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"アカウント設定"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"フォルダを変更しました。"</item>
     <item quantity="other" msgid="8918589141287976985">"フォルダを変更しました。"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"検索結果"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"このアカウントでは検索をご利用いただけません。"</string>
     <string name="searchMode" msgid="3329807422114758583">"検索モード"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 29c93ac..842dbb1 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"이동"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"폴더 설정"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"폴더"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"동기화 및 알림"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"폴더 설정"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"계정 설정"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"폴더가 변경되었습니다."</item>
     <item quantity="other" msgid="8918589141287976985">"폴더가 변경되었습니다."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"검색결과"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"이 계정에서는 검색이 지원되지 않습니다."</string>
     <string name="searchMode" msgid="3329807422114758583">"검색 모드"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index b3cfd02..23944b8 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Perkelti į"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Aplankų nustatymai"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Aplankai"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinchronizuoti ir pranešti"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Aplankų nustatymai"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Paskyros nustatymai"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Aplankas pakeistas."</item>
     <item quantity="other" msgid="8918589141287976985">"Aplankai pakeisti."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Rezultatai"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Šioje paskyroje paieška nepalaikoma."</string>
     <string name="searchMode" msgid="3329807422114758583">"Paieškos režimas"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 7503708..bef8502 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Pārvietot uz:"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mapju iestatījumi"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mapes"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinhronizācija un paziņojumi"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mapes iestatījumi"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Konta iestatījumi"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Mape ir mainīta."</item>
     <item quantity="other" msgid="8918589141287976985">"Mapes ir mainītas."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Rezultāti"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Šajā kontā netiek atbalstīta meklēšana."</string>
     <string name="searchMode" msgid="3329807422114758583">"Meklēšanas režīms"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 150a4cc..0c364af 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Alih ke"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Tetapan folder"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Folder"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Segerakkan &amp; beritahu"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Tetapan folder"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Tetapan akaun"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Folder yang diubah."</item>
     <item quantity="other" msgid="8918589141287976985">"Folder yang diubah."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Hasil"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Carian tidak disokong pada akaun ini."</string>
     <string name="searchMode" msgid="3329807422114758583">"Cari dalam Mod"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 48da52c..656ebd4 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Flytt til"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mappeinnstillinger"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mapper"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synkronisering og varsler"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mappeinnstillinger"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Kontoinnstillinger"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Endret mappe."</item>
     <item quantity="other" msgid="8918589141287976985">"Endret mapper."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultater"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Søk støttes ikke på denne kontoen."</string>
     <string name="searchMode" msgid="3329807422114758583">"Søkemodus"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 9f2e54c..cc91bda 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Verplaatsen naar"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mapinstellingen"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mappen"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchroniseren en melden"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mapinstellingen"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Accountinstellingen"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Map gewijzigd."</item>
     <item quantity="other" msgid="8918589141287976985">"Mappen gewijzigd."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultaten"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Zoeken wordt niet ondersteund in dit account."</string>
     <string name="searchMode" msgid="3329807422114758583">"Zoekmodus"</string>
@@ -277,7 +283,7 @@
   <string-array name="sync_status">
     <item msgid="2446076619901049026">"Geslaagd"</item>
     <item msgid="7109065688039971961">"Geen verbinding."</item>
-    <item msgid="8437496123716232060">"Kan niet aanmelden."</item>
+    <item msgid="8437496123716232060">"Kan niet inloggen."</item>
     <item msgid="1651266301325684887">"Beveiligingsfout."</item>
     <item msgid="1461520171154288533">"Kan niet synchroniseren."</item>
     <item msgid="4779810016424303449">"Interne fout"</item>
@@ -323,7 +329,7 @@
     <item msgid="6593672292311851204">"Veelgebruikt"</item>
     <item msgid="3584541772344786752">"Alle mappen"</item>
   </string-array>
-    <string name="signin" msgid="8958889809095796177">"Aanmelden"</string>
+    <string name="signin" msgid="8958889809095796177">"Inloggen"</string>
     <string name="info" msgid="6009817562073541204">"Info"</string>
     <string name="report" msgid="5417082746232614958">"Rapporteren"</string>
     <string name="sync_error" msgid="7368819509040597851">"Kan niet synchroniseren."</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 1ee0c72..45efbaf 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Przenieś do"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Ustawienia folderów"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Foldery"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchronizuj i powiadamiaj"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Ustawienia folderu"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Ustawienia konta"</string>
@@ -219,6 +223,8 @@
     <item quantity="one" msgid="4930161390461457462">"Zmieniono folder."</item>
     <item quantity="other" msgid="8918589141287976985">"Zmieniono foldery."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Wyniki"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Wyszukiwanie nie jest obsługiwane na tym koncie."</string>
     <string name="searchMode" msgid="3329807422114758583">"Tryb wyszukiwania"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 6f7f31f..b33baa4 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mover para"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Definições da pasta"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Pastas"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizar e notificar"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Definições da pasta"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Definições da conta"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Pasta alterada."</item>
     <item quantity="other" msgid="8918589141287976985">"Pastas alteradas."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultados"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"A pesquisa não é suportada nesta conta."</string>
     <string name="searchMode" msgid="3329807422114758583">"Modo de Pesquisa"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 4e8bea7..ee01f8d 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mover para"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Configurações de pastas"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Pastas"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizar e notificar"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Configurações da pasta"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Configurações da conta"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Pasta alterada."</item>
     <item quantity="other" msgid="8918589141287976985">"Pastas alteradas."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultados"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Não há suporte para pesquisa nesta conta."</string>
     <string name="searchMode" msgid="3329807422114758583">"Modo de pesquisa"</string>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index 0c579ff..a47b6ce 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -129,6 +129,10 @@
     <skip />
     <!-- no translation found for folder_list_title (4276644062440415214) -->
     <skip />
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <!-- no translation found for manage_folders_subtitle (7702199674083260433) -->
     <skip />
     <!-- no translation found for menu_folder_options (8897520487430647932) -->
@@ -321,6 +325,8 @@
     <skip />
     <!-- no translation found for conversation_folder_changed:one (4930161390461457462) -->
     <!-- no translation found for conversation_folder_changed:other (8918589141287976985) -->
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <!-- no translation found for search_results_header (4669917471897026269) -->
     <skip />
     <!-- no translation found for search_unsupported (4654227193354052607) -->
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 2b38507..f537450 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -63,8 +63,8 @@
     <string name="report_spam" msgid="6467567747975393907">"Raportaţi ca spam"</string>
     <string name="mark_not_spam" msgid="694891665407228160">"Nu este spam"</string>
     <string name="report_phishing" msgid="5714205737453138338">"Raportaţi phishing"</string>
-    <string name="delete" msgid="844871204175957681">"Ştergeţi"</string>
-    <string name="discard_drafts" msgid="6862272443470085375">"Ştergeţi mesajele nefinalizate"</string>
+    <string name="delete" msgid="844871204175957681">"Ștergeţi"</string>
+    <string name="discard_drafts" msgid="6862272443470085375">"Ștergeţi mesajele nefinalizate"</string>
     <string name="next" msgid="4674401197968248302">"Mai vechi"</string>
     <string name="previous" msgid="309943944831349924">"Mai noi"</string>
     <string name="refresh" msgid="490989798005710951">"Actualizaţi"</string>
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Mutați în"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Setări pentru dosare"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Dosare"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sincronizare şi notificare"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Setări pentru dosar"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Setările contului"</string>
@@ -167,16 +171,16 @@
     <string name="me" msgid="6480762904022198669">"eu"</string>
     <string name="show_all_folders" msgid="3281420732307737553">"Afişaţi toate dosarele"</string>
   <plurals name="confirm_delete_conversation">
-    <item quantity="one" msgid="3731948757247905508">"Ştergeţi această conversaţie?"</item>
-    <item quantity="other" msgid="930334208937121234">"Ştergeţi aceste <xliff:g id="COUNT">%1$d</xliff:g> (de) conversaţii?"</item>
+    <item quantity="one" msgid="3731948757247905508">"Ștergeţi această conversaţie?"</item>
+    <item quantity="other" msgid="930334208937121234">"Ștergeţi aceste <xliff:g id="COUNT">%1$d</xliff:g> (de) conversaţii?"</item>
   </plurals>
   <plurals name="confirm_archive_conversation">
     <item quantity="one" msgid="2990537295519552069">"Arhivaţi această conversaţie?"</item>
     <item quantity="other" msgid="4713469868399246772">"Arhivaţi aceste <xliff:g id="COUNT">%1$d</xliff:g> (de) conversaţii?"</item>
   </plurals>
   <plurals name="confirm_discard_drafts_conversation">
-    <item quantity="one" msgid="5974090449454432874">"Ştergeţi mesajele nefinalizate din conversaţie?"</item>
-    <item quantity="other" msgid="4173815457177336569">"Ştergeţi mesajele nefinalizate din <xliff:g id="COUNT">%1$d</xliff:g> conversaţii?"</item>
+    <item quantity="one" msgid="5974090449454432874">"Ștergeţi mesajele nefinalizate din conversaţie?"</item>
+    <item quantity="other" msgid="4173815457177336569">"Ștergeţi mesajele nefinalizate din <xliff:g id="COUNT">%1$d</xliff:g> conversaţii?"</item>
   </plurals>
     <string name="confirm_discard_text" msgid="1149834186404614612">"Renunţaţi la acest mesaj?"</string>
     <string name="loading_conversations" msgid="2649440958602369555">"Se încarcă…"</string>
@@ -214,13 +218,15 @@
     <item quantity="one" msgid="4398693029405479323">"&lt;b&gt;<xliff:g id="COUNT">%1$d</xliff:g>&lt;/b&gt; a fost ştearsă."</item>
     <item quantity="other" msgid="8630099095360065837">"&lt;b&gt;<xliff:g id="COUNT">%1$d</xliff:g>&lt;/b&gt; au fost şterse."</item>
   </plurals>
-    <string name="deleted" msgid="2757349161107268029">"Ştearsă"</string>
+    <string name="deleted" msgid="2757349161107268029">"Ștearsă"</string>
     <string name="archived" msgid="7533995360704366325">"Arhivată"</string>
     <string name="folder_removed" msgid="1047474677580149436">"Eliminat din <xliff:g id="FOLDERNAME">%1$s</xliff:g>"</string>
   <plurals name="conversation_folder_changed">
     <item quantity="one" msgid="4930161390461457462">"Dosar modificat."</item>
     <item quantity="other" msgid="8918589141287976985">"Dosare modificate."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Rezultate"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Căutarea nu este acceptată pentru acest cont."</string>
     <string name="searchMode" msgid="3329807422114758583">"Modul Căutare"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index c78e3b8..47726e7 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Переместить в"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Настройки папок"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Папки"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Синхронизация и уведомления"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Настройки папки"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Настройки аккаунта"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Папка изменена."</item>
     <item quantity="other" msgid="8918589141287976985">"Папки изменены."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Результаты"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"В этом аккаунте не поддерживается поиск."</string>
     <string name="searchMode" msgid="3329807422114758583">"Режим поиска"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index eb2addd..534430b 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Presunúť do"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Nastavenia priečinka"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Priečinky"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synchronizovať a upozorniť"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Nastavenia priečinka"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Nastavenia účtu"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Zmenený priečinok."</item>
     <item quantity="other" msgid="8918589141287976985">"Zmenené priečinky."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Výsledky"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Hľadanie nie je v tomto účte podporované."</string>
     <string name="searchMode" msgid="3329807422114758583">"Režim vyhľadávania"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 52649a9..d406dc9 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Premakni v"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Nastavitve mape"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mape"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sinhronizacija in obveščanje"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Nastavitve mape"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Nastavitve računa"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Spremenjena mapa."</item>
     <item quantity="other" msgid="8918589141287976985">"Spremenjene mape."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Rezultati"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Iskanje ni podprto za ta račun."</string>
     <string name="searchMode" msgid="3329807422114758583">"Način iskanja"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 45018d9..77bb3f2 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Премести у"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Подешавања директоријума"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Директоријуми"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Синхронизовање и обавештавање"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Подешавања директоријума"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Подешавања налога"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Директоријум је промењен."</item>
     <item quantity="other" msgid="8918589141287976985">"Директоријуми су промењени."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Резултати"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Претрага није подржана на овом налогу."</string>
     <string name="searchMode" msgid="3329807422114758583">"Режим претраге"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 0dd55de7..021a3e8 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Flytta till"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mappinställningar"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mappar"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Synka och meddela"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mappinställningar"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Kontoinställningar"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Mappen har ändrats."</item>
     <item quantity="other" msgid="8918589141287976985">"Mapparna har ändrats."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Resultat"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Det går inte att söka i det här kontot."</string>
     <string name="searchMode" msgid="3329807422114758583">"Sökläge"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 50ed7c8..1ddf455 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Hamisha hadi"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mipangilio ya folda"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Folda"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Sawazisha na uarifu"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mipangilio ya folda"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Mipangilio ya akaunti"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Folda iliyobadilishwa."</item>
     <item quantity="other" msgid="8918589141287976985">"Folda zilizobadilishwa."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Matokeo"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Utafutaji hauauniwi kwenye akaunti hii."</string>
     <string name="searchMode" msgid="3329807422114758583">"Hali ya Utafutaji"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 3f5c5d5..a638516 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"ย้ายไปที่"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"การตั้งค่าโฟลเดอร์"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"โฟลเดอร์"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"ซิงค์และแจ้งเตือน"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"การตั้งค่าโฟลเดอร์"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"การตั้งค่าบัญชี"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"เปลี่ยนโฟลเดอร์แล้ว"</item>
     <item quantity="other" msgid="8918589141287976985">"เปลี่ยนโฟลเดอร์แล้ว"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"ผลการค้นหา"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"บัญชีนี้ไม่สนับสนุนการค้นหา"</string>
     <string name="searchMode" msgid="3329807422114758583">"โหมดการค้นหา"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index e98da52..5c00f6f 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Ilipat sa"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Mga setting ng folder"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Mga Folder"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"I-sync at i-notify"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Mga setting ng folder"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Mga setting ng account"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Binagong folder."</item>
     <item quantity="other" msgid="8918589141287976985">"Mga binagong folder."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Mga resulta"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Hindi sinusuportahan ang paghahanap sa account na ito."</string>
     <string name="searchMode" msgid="3329807422114758583">"Mode ng Paghahanap"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index b6afb41..27233f2 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Taşı"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Klasör ayarları"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Klasörler"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Senkronize et ve bildir"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Klasör ayarları"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Hesap ayarları"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Klasör değişti."</item>
     <item quantity="other" msgid="8918589141287976985">"Klasörler değişti."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Sonuçlar"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Bu hesapta arama desteklenmiyor"</string>
     <string name="searchMode" msgid="3329807422114758583">"Arama Modu"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index deaab0b..7986e2e 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Перемістити в"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Налаштування папки"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Папки"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Синхронізація та сповіщення"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Налаштування папки"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Налаштування облікового запису"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Змінено папку."</item>
     <item quantity="other" msgid="8918589141287976985">"Змінено папки."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Результати"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Функція пошуку в цьому обліковому записі не підтримується."</string>
     <string name="searchMode" msgid="3329807422114758583">"Режим пошуку"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 8d490ec..6aa6ac7 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Di chuyển tới"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Cài đặt thư mục"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Thư mục"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Đồng bộ hóa và thông báo"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Cài đặt thư mục"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Cài đặt tài khoản"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Đã thay đổi thư mục."</item>
     <item quantity="other" msgid="8918589141287976985">"Đã thay đổi thư mục."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Kết quả"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Không hỗ trợ tính năng tìm kiếm trên tài khoản này."</string>
     <string name="searchMode" msgid="3329807422114758583">"Chế độ tìm kiếm"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 79a9237..a3ffadb 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"移至"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"文件夹设置"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"文件夹"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"同步与通知"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"文件夹设置"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"帐户设置"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"已更改文件夹。"</item>
     <item quantity="other" msgid="8918589141287976985">"已更改文件夹。"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"结果"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"此帐户不支持搜索。"</string>
     <string name="searchMode" msgid="3329807422114758583">"搜索模式"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 2385432..ee35ca4 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"移至"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"資料夾設定"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"資料夾"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"同步處理並通知"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"資料夾設定"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"帳戶設定"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"已變更資料夾。"</item>
     <item quantity="other" msgid="8918589141287976985">"已變更資料夾。"</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"搜尋結果"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"這個帳戶不支援搜尋功能。"</string>
     <string name="searchMode" msgid="3329807422114758583">"搜尋模式"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index efd7aea..ed52d66 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -77,6 +77,10 @@
     <string name="menu_move_to" msgid="9138296669516358542">"Hambisa ku-"</string>
     <string name="menu_manage_folders" msgid="6755623004628177492">"Izilungiselelo zefolda"</string>
     <string name="folder_list_title" msgid="4276644062440415214">"Amafolda"</string>
+    <!-- no translation found for folder_list_more (537172187223133825) -->
+    <skip />
+    <!-- no translation found for folder_list_show_all_accounts (8054807182336991835) -->
+    <skip />
     <string name="manage_folders_subtitle" msgid="7702199674083260433">"Ukuvumelanisa  &amp; ukuqaphelisa"</string>
     <string name="menu_folder_options" msgid="8897520487430647932">"Izilungiselelo zefolda"</string>
     <string name="menu_account_settings" msgid="8230989362863431918">"Izilungiselelo ze-akhawunti"</string>
@@ -221,6 +225,8 @@
     <item quantity="one" msgid="4930161390461457462">"Ifolda eshintshiwe."</item>
     <item quantity="other" msgid="8918589141287976985">"Amafolda ashintshiwe."</item>
   </plurals>
+    <!-- no translation found for conversation_folder_moved (297469098857964678) -->
+    <skip />
     <string name="search_results_header" msgid="4669917471897026269">"Imiphumela"</string>
     <string name="search_unsupported" msgid="4654227193354052607">"Usesho alusekelwe kule akhawunti."</string>
     <string name="searchMode" msgid="3329807422114758583">"Imodi yokusesha"</string>
diff --git a/res/values/accountprovider.xml b/res/values/accountprovider.xml
new file mode 100644
index 0000000..742a7e5
--- /dev/null
+++ b/res/values/accountprovider.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<resources>
+    <!-- List of content provider uris for  -->
+    <string-array name="account_providers" translatable="false">
+        <!-- mock account list -->
+        <item>content://com.android.mail.mockprovider/accounts</item>
+    </string-array>
+
+</resources>
\ No newline at end of file
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 84042ce..0039aab 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -21,4 +21,5 @@
     <item type="id" name="reply_state" />
     <item type="id" name="manage_folders_item"/>
     <item type="id" name="contact_image" />
+    <item type="id" name="move_folder" />
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 10d58df..dee3df6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -153,8 +153,24 @@
     <string name="menu_move_to">Move to</string>
     <!-- Menu item: manages the folders for this account. [CHAR LIMIT = 30] -->
     <string name="menu_manage_folders">Folder settings</string>
+    <!-- Menu item: report an email was not readable or poorly rendered -->
+    <string name="report_rendering_problem" translatable="false">Looks bad</string>
+    <!-- Menu item: report an email's readability has improved -->
+    <string name="report_rendering_improvement" translatable="false">Looks good</string>
+    <!-- Temporary text used for reporting rendering issues Googlers see in testing -->
+    <string name="report_rendering_problem_desc" translatable="false">
+        This message looks bad.
+    </string>
+    <!-- Temporary text used for reporting rendering improvements Googlers see in testing -->
+    <string name="report_rendering_improvement_desc" translatable="false">
+        This message looks good.
+    </string>
     <!-- Title for the Folder list screen. [CHAR LIMIT = 30] -->
     <string name="folder_list_title">Folders</string>
+    <!-- Folder list item: show more folders. [CHAR LIMIT = 30] -->
+    <string name="folder_list_more">More</string>
+    <!-- Folder list item: show all accounts. [CHAR LIMIT = 30] -->
+    <string name="folder_list_show_all_accounts">More accounts</string>
     <!-- action bar sub title for manage folder mode. [CHAR LIMIT = 30] -->
     <string name="manage_folders_subtitle">Sync &amp; notify</string>
     <!-- Menu item: options for this folder. When source text cannot be translated within the char limit, please translate the shorter "Folder options" instead. [CHAR LIMIT = 30] -->
@@ -440,6 +456,9 @@
         <item quantity="other">Changed folders.</item>
     </plurals>
 
+    <!-- Displayed after moving a conversation to a different folder. [CHAR LIMIT=100] -->
+    <string name="conversation_folder_moved">Moved to <xliff:g id="folderName">%1$s</xliff:g></string>
+
     <!-- Search Results: Text for header that is shown above search results [CHAR LIMIT=30] -->
     <string name="search_results_header">Results</string>
     <!-- Toast shown when the user taps the search hard key when viewing an account that does not support search [CHAR LIMIT=100] -->
diff --git a/src/com/android/mail/adapter/DrawerItem.java b/src/com/android/mail/adapter/DrawerItem.java
new file mode 100644
index 0000000..84b6540
--- /dev/null
+++ b/src/com/android/mail/adapter/DrawerItem.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 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.adapter;
+
+import com.android.mail.R;
+import com.android.mail.providers.Account;
+import com.android.mail.providers.Folder;
+import com.android.mail.ui.ControllableActivity;
+import com.android.mail.ui.FolderItemView;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
+
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/** An account, a system folder, a recent folder, or a header (a resource string) */
+public class DrawerItem {
+
+    private static final String LOG_TAG = LogTag.getLogTag();
+    public int mPosition;
+    public final Folder mFolder;
+    public final Account mAccount;
+    public final int mResource;
+    /** True if expand item view for expanding accounts. False otherwise */
+    public final boolean mIsExpandForAccount;
+    /** Either {@link #VIEW_ACCOUNT}, {@link #VIEW_FOLDER} or {@link #VIEW_HEADER} */
+    public final int mType;
+    /** A normal folder, also a child, if a parent is specified. */
+    public static final int VIEW_FOLDER = 0;
+    /** A text-label which serves as a header in sectioned lists. */
+    public static final int VIEW_HEADER = 1;
+    /** An account object, which allows switching accounts rather than folders. */
+    public static final int VIEW_ACCOUNT = 2;
+    /** An expandable object for expanding/collapsing more of the list */
+    public static final int VIEW_MORE = 3;
+    /** TODO: On adding another type, be sure to change getViewTypes() */
+
+    /** The parent activity */
+    private final ControllableActivity mActivity;
+    private final LayoutInflater mInflater;
+
+    /**
+     * Either {@link #FOLDER_SYSTEM}, {@link #FOLDER_RECENT} or {@link #FOLDER_USER} when
+     * {@link #mType} is {@link #VIEW_FOLDER}, or an {@link #ACCOUNT} in the case of
+     * accounts, {@link #EXPAND} for expand blocks, and {@link #INERT_HEADER} otherwise.
+     */
+    public final int mFolderType;
+    /** An unclickable text-header visually separating the different types. */
+    public static final int INERT_HEADER = 0;
+    /** A system-defined folder: Inbox/Drafts, ...*/
+    public static final int FOLDER_SYSTEM = 1;
+    /** A folder from whom a conversation was recently viewed */
+    public static final int FOLDER_RECENT = 2;
+    /** A user created folder */
+    public static final int FOLDER_USER = 3;
+    /** An entry for the accounts the user has on the device. */
+    public static final int ACCOUNT = 4;
+    /** A clickable block to expand list as requested */
+    public static final int EXPAND = 5;
+
+    /** True if this view is enabled, false otherwise. */
+    private boolean isEnabled = false;
+
+    /**
+     * Create a folder item with the given type.
+     * @param folder a folder that this item represents
+     * @param folderType one of {@link #FOLDER_SYSTEM}, {@link #FOLDER_RECENT} or
+     * {@link #FOLDER_USER}
+     */
+    public DrawerItem(ControllableActivity activity, Folder folder, int folderType,
+            int cursorPosition) {
+        mActivity = activity;
+        mInflater = LayoutInflater.from(mActivity.getActivityContext());
+        mFolder = folder;
+        mAccount = null;
+        mResource = -1;
+        mType = VIEW_FOLDER;
+        mFolderType = folderType;
+        mPosition = cursorPosition;
+        mIsExpandForAccount = false;
+    }
+
+    /**
+     * Creates an item from an account.
+     * @param account an account that this item represents.
+     */
+    public DrawerItem(ControllableActivity activity, Account account, int count) {
+        mActivity = activity;
+        mInflater = LayoutInflater.from(mActivity.getActivityContext());
+        mFolder = null;
+        mType = VIEW_ACCOUNT;
+        mResource = count;
+        mFolderType = ACCOUNT;
+        mAccount = account;
+        mIsExpandForAccount = false;
+    }
+
+    /**
+     * Create a header item with a string resource.
+     * @param resource the string resource: R.string.all_folders_heading
+     */
+    public DrawerItem(ControllableActivity activity, int resource) {
+        mActivity = activity;
+        mInflater = LayoutInflater.from(mActivity.getActivityContext());
+        mFolder = null;
+        mResource = resource;
+        mType = VIEW_HEADER;
+        mFolderType = INERT_HEADER;
+        mAccount = null;
+        mIsExpandForAccount = false;
+    }
+
+    /**
+     * Creates an item for expanding or contracting for emails/items
+     * @param resource the string resource: R.string.folder_list_*
+     * @param isExpand true if "more" and false if "less"
+     */
+    public DrawerItem(ControllableActivity activity, int resource, boolean isExpandForAccount) {
+        mActivity = activity;
+        mInflater = LayoutInflater.from(mActivity.getActivityContext());
+        mFolder = null;
+        mType = VIEW_MORE;
+        mResource = resource;
+        mFolderType = EXPAND;
+        mAccount = null;
+        mIsExpandForAccount = isExpandForAccount;
+    }
+
+    public View getView(int position, View convertView, ViewGroup parent) {
+        final View result;
+        switch (mType) {
+            case VIEW_FOLDER:
+                result = getFolderView(position, convertView, parent);
+                break;
+            case VIEW_HEADER:
+                result = getHeaderView(position, convertView, parent);
+                break;
+            case VIEW_ACCOUNT:
+                result = getAccountView(position, convertView, parent);
+                break;
+            case VIEW_MORE:
+                result = getExpandView(position, convertView, parent);
+                break;
+            default:
+                LogUtils.wtf(LOG_TAG, "DrawerItem.getView(%d) for an invalid type!", mType);
+                result = null;
+        }
+        return result;
+    }
+
+    /**
+     * Book-keeping for how many different view types there are. Be sure to
+     * increment this appropriately once adding more types as drawer items
+     * @return number of different types of view items
+     */
+    public static int getViewTypes() {
+        return VIEW_MORE + 1;
+    }
+
+    /**
+     * Returns whether this view is enabled or not.
+     * @return
+     */
+    public boolean isItemEnabled(Uri currentAccountUri) {
+        switch (mType) {
+            case VIEW_HEADER :
+                // Headers are never enabled.
+                return false;
+            case VIEW_FOLDER :
+                // Folders are always enabled.
+                return true;
+            case VIEW_ACCOUNT:
+                // Accounts are only enabled if they are not the current account.
+                return !currentAccountUri.equals(mAccount.uri);
+            case VIEW_MORE:
+                // 'Expand/Collapse' items are always enabled.
+                return true;
+            default:
+                LogUtils.wtf(LOG_TAG, "DrawerItem.isItemEnabled() for invalid type %d", mType);
+                return false;
+        }
+    }
+
+    /**
+     * Returns whether this view is highlighted or not.
+     *
+     * @param currentFolder
+     * @param currentType
+     * @return
+     */
+    public boolean isHighlighted(Folder currentFolder, int currentType){
+        switch (mType) {
+            case VIEW_HEADER :
+                // Headers are never highlighted
+                return false;
+            case VIEW_FOLDER :
+                return (mFolderType == currentType) && mFolder.uri.equals(currentFolder.uri);
+            case VIEW_ACCOUNT:
+                // Accounts are never highlighted
+                return false;
+            case VIEW_MORE:
+                // Expand/Collapse items are never highlighted
+                return false;
+            default:
+                LogUtils.wtf(LOG_TAG, "DrawerItem.isHighlighted() for invalid type %d", mType);
+                return false;
+        }
+    }
+
+    /**
+     * Return a view for an account object.
+     * @param position a zero indexed position in to the list.
+     * @param convertView a view, possibly null, to be recycled.
+     * @param parent the parent viewgroup to attach to.
+     * @return a view to display at this position.
+     */
+    private View getAccountView(int position, View convertView, ViewGroup parent) {
+        // Shoe-horn an account object into a Folder DrawerItem for now.
+        // TODO(viki): Stop this ugly shoe-horning and use a real layout.
+        final FolderItemView folderItemView;
+        if (convertView != null) {
+            folderItemView = (FolderItemView) convertView;
+        } else {
+            folderItemView =
+                    (FolderItemView) mInflater.inflate(R.layout.folder_item, null, false);
+        }
+        // Temporary. Ideally we want a totally different item.
+        folderItemView.bind(mAccount, mActivity, mResource);
+        View v = folderItemView.findViewById(R.id.color_block);
+        v.setBackgroundColor(mAccount.color);
+        v = folderItemView.findViewById(R.id.folder_icon);
+        v.setVisibility(View.GONE);
+        return folderItemView;
+    }
+
+    /**
+     * Returns a text divider between sections.
+     * @param convertView a previous view, perhaps null
+     * @param parent the parent of this view
+     * @return a text header at the given position.
+     */
+    private View getHeaderView(int position, View convertView, ViewGroup parent) {
+        final TextView headerView;
+        if (convertView != null) {
+            headerView = (TextView) convertView;
+        } else {
+            headerView = (TextView) mInflater.inflate(
+                    R.layout.folder_list_header, parent, false);
+        }
+        headerView.setText(mResource);
+        return headerView;
+    }
+
+    /**
+     * Return a folder: either a parent folder or a normal (child or flat)
+     * folder.
+     * @param position a zero indexed position into the top level list.
+     * @param convertView a view, possibly null, to be recycled.
+     * @param parent the parent hosting this view.
+     * @return a view showing a folder at the given position.
+     */
+    private View getFolderView(int position, View convertView, ViewGroup parent) {
+        final FolderItemView folderItemView;
+        if (convertView != null) {
+            folderItemView = (FolderItemView) convertView;
+        } else {
+            folderItemView =
+                    (FolderItemView) mInflater.inflate(R.layout.folder_item, null, false);
+        }
+        folderItemView.bind(mFolder, mActivity);
+        Folder.setFolderBlockColor(mFolder, folderItemView.findViewById(R.id.color_block));
+        Folder.setIcon(mFolder, (ImageView) folderItemView.findViewById(R.id.folder_icon));
+        return folderItemView;
+    }
+
+    /**
+     * Return a view for the 'Expand/Collapse' item.
+     * @param position a zero indexed position into the top level list.
+     * @param convertView a view, possibly null, to be recycled.
+     * @param parent the parent hosting this view.
+     * @return a view showing an item for folder/account expansion at given position.
+     */
+    private View getExpandView(int position, View convertView, ViewGroup parent) {
+        final ViewGroup headerView;
+        if (convertView != null) {
+            headerView = (ViewGroup) convertView;
+        } else {
+            headerView = (ViewGroup) mInflater.inflate(
+                    R.layout.folder_expand_item, parent, false);
+        }
+        TextView direction =
+                (TextView)headerView.findViewById(R.id.folder_expand_text);
+        if(direction != null) {
+            direction.setText(mResource);
+        }
+        return headerView;
+    }
+}
+
diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java
index f47f7fd..b3c9f79 100644
--- a/src/com/android/mail/browse/ConversationCursor.java
+++ b/src/com/android/mail/browse/ConversationCursor.java
@@ -74,7 +74,7 @@
  * caching for quick UI response. This is effectively a singleton class, as the cache is
  * implemented as a static HashMap.
  */
-public final class ConversationCursor implements Cursor {
+public final class ConversationCursor implements Cursor, ConversationCursorMarkSeenListener {
 
     private static final boolean ENABLE_CONVERSATION_PRECACHING = true;
 
@@ -2101,4 +2101,12 @@
             });
         }
     }
+
+    /**
+     * Marks all contents of this cursor as seen. This may have no effect with certain providers.
+     */
+    @Override
+    public void markContentsSeen() {
+        ConversationCursorMarkSeenListener.MarkSeenHelper.markContentsSeen(mUnderlyingCursor);
+    }
 }
diff --git a/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java b/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java
new file mode 100644
index 0000000..0956859
--- /dev/null
+++ b/src/com/android/mail/browse/ConversationCursorMarkSeenListener.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ *      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.database.Cursor;
+import android.database.CursorWrapper;
+
+public interface ConversationCursorMarkSeenListener {
+    /**
+     * Marks all contents of this cursor as seen.
+     */
+    void markContentsSeen();
+
+    public class MarkSeenHelper {
+        /**
+         * Invokes {@link ConversationCursorMarkSeenListener#markContentsSeen(Cursor)} on the
+         * specified {@link Cursor}, recursively calls {@link #markContentsSeen(Cursor)} on a
+         * wrapped cursor, or returns.
+         */
+        public static void markContentsSeen(final Cursor cursor) {
+            if (cursor == null) {
+                return;
+            }
+
+            if (cursor instanceof ConversationCursorMarkSeenListener) {
+                ((ConversationCursorMarkSeenListener) cursor).markContentsSeen();
+            } else if (cursor instanceof CursorWrapper) {
+                markContentsSeen(((CursorWrapper) cursor).getWrappedCursor());
+            }
+        }
+    }
+}
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index 9ef50cd..5165610 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -72,7 +72,6 @@
 import com.android.mail.ui.AnimatedAdapter;
 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.EllipsizedMultilineTextView;
@@ -1220,6 +1219,7 @@
      * Toggle the check mark on this view and update the conversation or begin
      * drag, if drag is enabled.
      */
+    @Override
     public void toggleCheckMarkOrBeginDrag() {
         ViewMode mode = mActivity.getViewMode();
         if (!mTabletDevice || !mode.isListMode()) {
@@ -1267,9 +1267,11 @@
         postInvalidate(mCoordinates.starX, mCoordinates.starY, mCoordinates.starX
                 + starBitmap.getWidth(),
                 mCoordinates.starY + starBitmap.getHeight());
-        ConversationCursor cursor = (ConversationCursor)mAdapter.getCursor();
-        cursor.updateBoolean(mContext, mHeader.conversation, ConversationColumns.STARRED,
-                mHeader.conversation.starred);
+        ConversationCursor cursor = (ConversationCursor) mAdapter.getCursor();
+        if (cursor != null) {
+            cursor.updateBoolean(mContext, mHeader.conversation, ConversationColumns.STARRED,
+                    mHeader.conversation.starred);
+        }
     }
 
     private boolean isTouchInCheckmark(float x, float y) {
diff --git a/src/com/android/mail/browse/ConversationPagerAdapter.java b/src/com/android/mail/browse/ConversationPagerAdapter.java
index c542733..239d6dc 100644
--- a/src/com/android/mail/browse/ConversationPagerAdapter.java
+++ b/src/com/android/mail/browse/ConversationPagerAdapter.java
@@ -31,6 +31,7 @@
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.Folder;
+import com.android.mail.providers.FolderObserver;
 import com.android.mail.providers.UIProvider;
 import com.android.mail.ui.AbstractConversationViewFragment;
 import com.android.mail.ui.ActivityController;
@@ -44,7 +45,12 @@
         implements ViewPager.OnPageChangeListener {
 
     private final DataSetObserver mListObserver = new ListObserver();
-    private final DataSetObserver mFolderObserver = new FolderObserver();
+    private final FolderObserver mFolderObserver = new FolderObserver() {
+        @Override
+        public void onChanged(Folder newFolder) {
+            notifyDataSetChanged();
+        }
+    };
     private ActivityController mController;
     private final Bundle mCommonFragmentArgs;
     private final Conversation mInitialConversation;
@@ -427,7 +433,7 @@
         mController = controller;
         if (mController != null && !mStopListeningMode) {
             mController.registerConversationListObserver(mListObserver);
-            mController.registerFolderObserver(mFolderObserver);
+            mFolderObserver.initialize(mController);
 
             notifyDataSetChanged();
         } else {
@@ -451,7 +457,7 @@
 
         if (mController != null) {
             mController.unregisterConversationListObserver(mListObserver);
-            mController.unregisterFolderObserver(mFolderObserver);
+            mFolderObserver.unregisterAndDestroy();
         }
         mLastKnownCount = getCount();
         mStopListeningMode = true;
@@ -484,14 +490,6 @@
         // no-op
     }
 
-    // update the pager title strip as the Folder's conversation count changes
-    private class FolderObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            notifyDataSetChanged();
-        }
-    }
-
     // update the pager dataset as the Controller's cursor changes
     private class ListObserver extends DataSetObserver {
         @Override
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index be8baad..8bd6981 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -16,13 +16,12 @@
 
 package com.android.mail.browse;
 
-import android.app.Dialog;
 import android.app.AlertDialog;
+import android.app.Dialog;
 import android.content.AsyncQueryHandler;
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.res.Resources;
 import android.database.DataSetObserver;
 import android.graphics.Typeface;
@@ -33,12 +32,11 @@
 import android.text.style.StyleSpan;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
+import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
-import android.widget.Button;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
@@ -55,6 +53,7 @@
 import com.android.mail.browse.MessageCursor.ConversationMessage;
 import com.android.mail.compose.ComposeActivity;
 import com.android.mail.perf.Timer;
+import com.android.mail.preferences.MailPrefs;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Address;
 import com.android.mail.providers.Folder;
@@ -64,7 +63,6 @@
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.Utils;
 import com.android.mail.utils.VeiledAddressMatcher;
-
 import com.google.common.annotations.VisibleForTesting;
 
 import java.io.IOException;
@@ -99,6 +97,10 @@
 
     public static final int POPUP_MODE = 1;
 
+    // This is a debug only feature
+    public static final boolean ENABLE_REPORT_RENDERING_PROBLEM =
+            MailPrefs.SHOW_EXPERIMENTAL_PREFS;
+
     private MessageHeaderViewCallbacks mCallbacks;
 
     private ViewGroup mUpperHeaderView;
@@ -227,6 +229,9 @@
         void showExternalResources(Message msg);
 
         void showExternalResources(String senderRawAddress);
+
+        boolean supportsMessageTransforms();
+        String getMessageTransforms(Message msg);
     }
 
     public MessageHeaderView(Context context) {
@@ -930,6 +935,16 @@
             case R.id.forward:
                 ComposeActivity.forward(getContext(), getAccount(), mMessage);
                 break;
+            case R.id.report_rendering_problem:
+                String text = getContext().getString(R.string.report_rendering_problem_desc);
+                ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage,
+                    text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
+                break;
+            case R.id.report_rendering_improvement:
+                text = getContext().getString(R.string.report_rendering_improvement_desc);
+                ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage,
+                    text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
+                break;
             case R.id.star: {
                 final boolean newValue = !v.isSelected();
                 v.setSelected(newValue);
@@ -948,8 +963,14 @@
                 }
                 final boolean defaultReplyAll = getAccount().settings.replyBehavior
                         == UIProvider.DefaultReplyBehavior.REPLY_ALL;
-                mPopup.getMenu().findItem(R.id.reply).setVisible(defaultReplyAll);
-                mPopup.getMenu().findItem(R.id.reply_all).setVisible(!defaultReplyAll);
+                final Menu m = mPopup.getMenu();
+                m.findItem(R.id.reply).setVisible(defaultReplyAll);
+                m.findItem(R.id.reply_all).setVisible(!defaultReplyAll);
+
+                final boolean reportRendering = ENABLE_REPORT_RENDERING_PROBLEM
+                    && mCallbacks.supportsMessageTransforms();
+                m.findItem(R.id.report_rendering_improvement).setVisible(reportRendering);
+                m.findItem(R.id.report_rendering_problem).setVisible(reportRendering);
 
                 mPopup.show();
                 break;
diff --git a/src/com/android/mail/compose/ComposeActivity.java b/src/com/android/mail/compose/ComposeActivity.java
index 31f4973..77c29d7 100644
--- a/src/com/android/mail/compose/ComposeActivity.java
+++ b/src/com/android/mail/compose/ComposeActivity.java
@@ -38,8 +38,8 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
-import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 import android.provider.BaseColumns;
 import android.text.Editable;
 import android.text.Html;
@@ -70,6 +70,7 @@
 import com.android.ex.chips.RecipientEditTextView;
 import com.android.mail.MailIntentService;
 import com.android.mail.R;
+import com.android.mail.browse.MessageHeaderView;
 import com.android.mail.compose.AttachmentsView.AttachmentAddedOrDeletedListener;
 import com.android.mail.compose.AttachmentsView.AttachmentFailureException;
 import com.android.mail.compose.FromAddressSpinner.OnAccountChangedListener;
@@ -86,10 +87,10 @@
 import com.android.mail.providers.UIProvider;
 import com.android.mail.providers.UIProvider.AccountCapabilities;
 import com.android.mail.providers.UIProvider.DraftType;
+import com.android.mail.ui.AttachmentTile.AttachmentPreview;
 import com.android.mail.ui.FeedbackEnabledActivity;
 import com.android.mail.ui.MailActivity;
 import com.android.mail.ui.WaitFragment;
-import com.android.mail.ui.AttachmentTile.AttachmentPreview;
 import com.android.mail.utils.AccountUtils;
 import com.android.mail.utils.AttachmentUtils;
 import com.android.mail.utils.ContentProviderTask;
@@ -116,8 +117,9 @@
 
 public class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener,
         RespondInlineListener, DialogInterface.OnClickListener, TextWatcher,
-        AttachmentAddedOrDeletedListener, OnAccountChangedListener, LoaderManager.LoaderCallbacks<Cursor>,
-        TextView.OnEditorActionListener, FeedbackEnabledActivity {
+        AttachmentAddedOrDeletedListener, OnAccountChangedListener,
+        LoaderManager.LoaderCallbacks<Cursor>, TextView.OnEditorActionListener,
+        FeedbackEnabledActivity {
     // Identifiers for which type of composition this is
     protected static final int COMPOSE = -1;
     protected static final int REPLY = 0;
@@ -205,6 +207,7 @@
     private static final String EXTRA_MESSAGE = "extraMessage";
     private static final int REFERENCE_MESSAGE_LOADER = 0;
     private static final int LOADER_ACCOUNT_CURSOR = 1;
+    private static final int INIT_DRAFT_USING_REFERENCE_MESSAGE = 2;
     private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount";
     private static final String TAG_WAIT = "wait-fragment";
     private static final String MIME_TYPE_PHOTO = "image/*";
@@ -262,6 +265,7 @@
     private RecipientTextWatcher mCcListener;
     private RecipientTextWatcher mBccListener;
     private Uri mRefMessageUri;
+    private boolean mShowQuotedText = false;
     private Bundle mSavedInstanceState;
 
 
@@ -280,14 +284,14 @@
      * Can be called from a non-UI thread.
      */
     public static void editDraft(Context launcher, Account account, Message message) {
-        launch(launcher, account, message, EDIT_DRAFT);
+        launch(launcher, account, message, EDIT_DRAFT, null, null);
     }
 
     /**
      * Can be called from a non-UI thread.
      */
     public static void compose(Context launcher, Account account) {
-        launch(launcher, account, null, COMPOSE);
+        launch(launcher, account, null, COMPOSE, null, null);
     }
 
     /**
@@ -322,24 +326,30 @@
      * Can be called from a non-UI thread.
      */
     public static void reply(Context launcher, Account account, Message message) {
-        launch(launcher, account, message, REPLY);
+        launch(launcher, account, message, REPLY, null, null);
     }
 
     /**
      * Can be called from a non-UI thread.
      */
     public static void replyAll(Context launcher, Account account, Message message) {
-        launch(launcher, account, message, REPLY_ALL);
+        launch(launcher, account, message, REPLY_ALL, null, null);
     }
 
     /**
      * Can be called from a non-UI thread.
      */
     public static void forward(Context launcher, Account account, Message message) {
-        launch(launcher, account, message, FORWARD);
+        launch(launcher, account, message, FORWARD, null, null);
     }
 
-    private static void launch(Context launcher, Account account, Message message, int action) {
+    public static void reportRenderingFeedback(Context launcher, Account account, Message message,
+            String body) {
+        launch(launcher, account, message, FORWARD, "android-gmail-readability@google.com", body);
+    }
+
+    private static void launch(Context launcher, Account account, Message message, int action,
+            String toAddress, String body) {
         Intent intent = new Intent(launcher, ComposeActivity.class);
         intent.putExtra(EXTRA_FROM_EMAIL_TASK, true);
         intent.putExtra(EXTRA_ACTION, action);
@@ -349,6 +359,12 @@
         } else {
             intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE, message);
         }
+        if (toAddress != null) {
+            intent.putExtra(EXTRA_TO, toAddress);
+        }
+        if (body != null) {
+            intent.putExtra(EXTRA_BODY, body);
+        }
         launcher.startActivity(intent);
     }
 
@@ -366,7 +382,7 @@
         Intent intent = getIntent();
         Message message;
         ArrayList<AttachmentPreview> previews;
-        boolean showQuotedText = false;
+        mShowQuotedText = false;
         int action;
         // Check for any of the possibly supplied accounts.;
         Account account = null;
@@ -418,14 +434,15 @@
         }
 
         if (mRefMessageUri != null) {
-            // We have a referenced message that we must look up.
-            getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this);
+            mShowQuotedText = true;
+            mComposeMode = action;
+            getLoaderManager().initLoader(INIT_DRAFT_USING_REFERENCE_MESSAGE, null, this);
             return;
         } else if (message != null && action != EDIT_DRAFT) {
             initFromDraftMessage(message);
             initQuotedTextFromRefMessage(mRefMessage, action);
             showCcBcc(savedInstanceState);
-            showQuotedText = message.appendRefMessageContent;
+            mShowQuotedText = message.appendRefMessageContent;
         } else if (action == EDIT_DRAFT) {
             initFromDraftMessage(message);
             boolean showBcc = !TextUtils.isEmpty(message.getBcc());
@@ -447,17 +464,29 @@
                     action = COMPOSE;
                     break;
             }
-            initQuotedTextFromRefMessage(mRefMessage, action);
-            showQuotedText = message.appendRefMessageContent;
+            LogUtils.d(LOG_TAG, "Previous draft had action type: %d", action);
+
+            mShowQuotedText = message.appendRefMessageContent;
+            if (message.refMessageUri != null) {
+                // If we're editing an existing draft that was in reference to an existing message,
+                // still need to load that original message since we might need to refer to the
+                // original sender and recipients if user switches "reply <-> reply-all".
+                mRefMessageUri = message.refMessageUri;
+                mComposeMode = action;
+                getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this);
+                return;
+            }
         } else if ((action == REPLY || action == REPLY_ALL || action == FORWARD)) {
             if (mRefMessage != null) {
                 initFromRefMessage(action);
-                showQuotedText = true;
+                mShowQuotedText = true;
             }
         } else {
             initFromExtras(intent);
         }
-        finishSetup(action, intent, savedInstanceState, showQuotedText);
+
+        mComposeMode = action;
+        finishSetup(action, intent, savedInstanceState);
     }
 
     private void checkValidAccounts() {
@@ -541,8 +570,7 @@
         return account;
     }
 
-    private void finishSetup(int action, Intent intent, Bundle savedInstanceState,
-            boolean showQuotedText) {
+    private void finishSetup(int action, Intent intent, Bundle savedInstanceState) {
         setFocus(action);
         if (action == COMPOSE) {
             mQuotedTextView.setVisibility(View.GONE);
@@ -553,7 +581,7 @@
         if (!hadSavedInstanceStateMessage(savedInstanceState)) {
             initAttachmentsFromIntent(intent);
         }
-        initActionBar(action);
+        initActionBar();
         initFromSpinner(savedInstanceState != null ? savedInstanceState : intent.getExtras(),
                 action);
 
@@ -565,7 +593,7 @@
 
         initChangeListeners();
         updateHideOrShowCcBcc();
-        updateHideOrShowQuotedText(showQuotedText);
+        updateHideOrShowQuotedText(mShowQuotedText);
 
         mRespondedInline = mSavedInstanceState != null ?
                 mSavedInstanceState.getBoolean(EXTRA_RESPONDED_INLINE) : false;
@@ -664,7 +692,7 @@
             addAttachmentAndUpdateView(data);
             mAddingAttachment = false;
         } else if (request == RESULT_CREATE_ACCOUNT) {
-                // We were waiting for the user to create an account
+            // We were waiting for the user to create an account
             if (result != RESULT_OK) {
                 finish();
             } else {
@@ -784,7 +812,7 @@
         message.bodyHtml = fullBody.toString();
         message.bodyText = mBodyView.getText().toString();
         message.embedsExternalResources = false;
-        message.refMessageId = mRefMessage != null ? mRefMessage.uri.toString() : null;
+        message.refMessageUri = mRefMessage != null ? mRefMessage.uri : null;
         message.appendRefMessageContent = mQuotedTextView.getQuotedTextIfIncluded() != null;
         ArrayList<Attachment> attachments = mAttachmentsView.getAttachments();
         message.hasAttachments = attachments != null && attachments.size() > 0;
@@ -1054,13 +1082,13 @@
         mAttachmentsView.setAttachmentChangesListener(this);
     }
 
-    private void initActionBar(int action) {
-        mComposeMode = action;
+    private void initActionBar() {
+        LogUtils.d(LOG_TAG, "initializing action bar in ComposeActivity");
         ActionBar actionBar = getActionBar();
         if (actionBar == null) {
             return;
         }
-        if (action == ComposeActivity.COMPOSE) {
+        if (mComposeMode == ComposeActivity.COMPOSE) {
             actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
             actionBar.setTitle(R.string.compose);
         } else {
@@ -1070,7 +1098,7 @@
             }
             actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
             actionBar.setListNavigationCallbacks(mComposeModeAdapter, this);
-            switch (action) {
+            switch (mComposeMode) {
                 case ComposeActivity.REPLY:
                     actionBar.setSelectedNavigationItem(0);
                     break;
@@ -1089,6 +1117,23 @@
 
     private void initFromRefMessage(int action) {
         setFieldsFromRefMessage(action);
+
+        // Check if To: address and email body needs to be prefilled based on extras.
+        // This is used for reporting rendering feedback.
+        if (MessageHeaderView.ENABLE_REPORT_RENDERING_PROBLEM) {
+            Intent intent = getIntent();
+            if (intent.getExtras() != null) {
+                String toAddresses = intent.getStringExtra(EXTRA_TO);
+                if (toAddresses != null) {
+                    addToAddresses(Arrays.asList(TextUtils.split(toAddresses, ",")));
+                }
+                String body = intent.getStringExtra(EXTRA_BODY);
+                if (body != null) {
+                    setBody(body, false /* withSignature */);
+                }
+            }
+        }
+
         if (mRefMessage != null) {
             // CC field only gets populated when doing REPLY_ALL.
             // BCC never gets auto-populated, unless the user is editing
@@ -3078,6 +3123,9 @@
     @Override
     public Loader<Cursor> onCreateLoader(int id, Bundle args) {
         switch (id) {
+            case INIT_DRAFT_USING_REFERENCE_MESSAGE:
+                return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null,
+                        null, null);
             case REFERENCE_MESSAGE_LOADER:
                 return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null,
                         null, null);
@@ -3092,14 +3140,13 @@
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
         int id = loader.getId();
         switch (id) {
-            case REFERENCE_MESSAGE_LOADER:
+            case INIT_DRAFT_USING_REFERENCE_MESSAGE:
                 if (data != null && data.moveToFirst()) {
                     mRefMessage = new Message(data);
                     Intent intent = getIntent();
-                    int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE);
-                    initFromRefMessage(action);
-                    finishSetup(action, intent, null, true);
-                    if (action != FORWARD) {
+                    initFromRefMessage(mComposeMode);
+                    finishSetup(mComposeMode, intent, null);
+                    if (mComposeMode != FORWARD) {
                         String to = intent.getStringExtra(EXTRA_TO);
                         if (!TextUtils.isEmpty(to)) {
                             mRefMessage.setTo(null);
@@ -3113,6 +3160,13 @@
                     finish();
                 }
                 break;
+            case REFERENCE_MESSAGE_LOADER:
+                // Only populate mRefMessage and leave other fields untouched.
+                if (data != null && data.moveToFirst()) {
+                    mRefMessage = new Message(data);
+                }
+                finishSetup(mComposeMode, getIntent(), mSavedInstanceState);
+                break;
             case LOADER_ACCOUNT_CURSOR:
                 if (data != null && data.moveToFirst()) {
                     // there are accounts now!
diff --git a/src/com/android/mail/content/ObjectCursorLoader.java b/src/com/android/mail/content/ObjectCursorLoader.java
index 227162f..a9a930f 100644
--- a/src/com/android/mail/content/ObjectCursorLoader.java
+++ b/src/com/android/mail/content/ObjectCursorLoader.java
@@ -20,7 +20,6 @@
 
 import android.content.AsyncTaskLoader;
 import android.content.Context;
-import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
 
@@ -54,6 +53,18 @@
     public ObjectCursorLoader(Context context, Uri uri, String[] projection,
             CursorCreator<T> factory) {
         super(context);
+
+        /*
+         * If these are null, it's going to crash anyway in loadInBackground(), but this stack trace
+         * is much more useful.
+         */
+        if (uri == null) {
+            throw new NullPointerException("The uri cannot be null");
+        }
+        if (factory == null) {
+            throw new NullPointerException("The factory cannot be null");
+        }
+
         mObserver = new ForceLoadContentObserver();
         mUri = uri;
         mProjection = projection;
@@ -68,7 +79,7 @@
         if (inner != null) {
             // Ensure the cursor window is filled
             inner.getCount();
-            registerContentObserver(inner, mObserver);
+            inner.registerContentObserver(mObserver);
         }
         // Modifications to the ObjectCursor, create an Object Cursor and fill the cache.
         final ObjectCursor<T> cursor = new ObjectCursor<T>(inner, mFactory);
@@ -76,14 +87,6 @@
         return cursor;
     }
 
-    /**
-     * Registers an observer to get notifications from the content provider
-     * when the cursor needs to be refreshed.
-     */
-    void registerContentObserver(Cursor cursor, ContentObserver observer) {
-        cursor.registerContentObserver(mObserver);
-    }
-
     /* Runs on the UI thread */
     @Override
     public void deliverResult(ObjectCursor<T> cursor) {
@@ -133,11 +136,10 @@
     }
 
     @Override
-    public boolean cancelLoad() {
-        if (mCursor != null && !mCursor.isClosed()) {
-            mCursor.close();
+    public void onCanceled(ObjectCursor<T> cursor) {
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
         }
-        return super.cancelLoad();
     }
 
     @Override
diff --git a/src/com/android/mail/preferences/MailPrefs.java b/src/com/android/mail/preferences/MailPrefs.java
index 88392ed..5a0b0d7 100644
--- a/src/com/android/mail/preferences/MailPrefs.java
+++ b/src/com/android/mail/preferences/MailPrefs.java
@@ -67,11 +67,11 @@
                 .add(CONVERSATION_LIST_SWIPE_ACTION)
                 .build();
 
-        private static final String ENABLE_FTS = "enable-fts";
         private static final String ENABLE_CHIP_DRAG_AND_DROP = "enable-chip-drag-and-drop";
         public static final String ENABLE_CONVLIST_PHOTOS = "enable-convlist-photos";
         public static final String ENABLE_WHOOSH_ZOOM = "enable-whoosh-zoom";
         public static final String ENABLE_MUNGE_TABLES = "enable-munge-tables";
+        public static final String ENABLE_MUNGE_IMAGES = "enable-munge-images";
         public static final String ENABLE_SECTIONED_INBOX_EXPERIMENT = "enable-sectioned-inbox";
 
     }
@@ -134,13 +134,6 @@
     }
 
     @SuppressWarnings("unused")
-    public boolean fullTextSearchEnabled() {
-        // If experimental preferences are not enabled, return true.
-        return !SHOW_EXPERIMENTAL_PREFS || getSharedPreferences().getBoolean(
-                PreferenceKeys.ENABLE_FTS, true);
-    }
-
-    @SuppressWarnings("unused")
     public boolean chipDragAndDropEnabled() {
         // If experimental preferences are not enabled, return false.
         return SHOW_EXPERIMENTAL_PREFS && getSharedPreferences().getBoolean(
@@ -176,6 +169,13 @@
                 PreferenceKeys.ENABLE_MUNGE_TABLES, true);
     }
 
+    @SuppressWarnings("unused")
+    public boolean shouldMungeImages() {
+        // If experimental preferences are not enabled, return false.
+        return SHOW_EXPERIMENTAL_PREFS && getSharedPreferences().getBoolean(
+                PreferenceKeys.ENABLE_MUNGE_IMAGES, true);
+    }
+
     private static String createWidgetPreferenceValue(Account account, String folderUri) {
         return account.uri.toString() + BaseWidgetProvider.ACCOUNT_FOLDER_PREFERENCE_SEPARATOR
                 + folderUri;
diff --git a/src/com/android/mail/providers/Account.java b/src/com/android/mail/providers/Account.java
index a33c8fa..5b8522f 100644
--- a/src/com/android/mail/providers/Account.java
+++ b/src/com/android/mail/providers/Account.java
@@ -726,7 +726,7 @@
         map.put(AccountColumns.SettingsColumns.SNAP_HEADERS, settings.snapHeaders);
         map.put(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, settings.replyBehavior);
         map.put(
-                AccountColumns.SettingsColumns.SHOW_CHECKBOXES, settings.showCheckboxes ? 1 : 0);
+                AccountColumns.SettingsColumns.HIDE_CHECKBOXES, settings.hideCheckboxes ? 1 : 0);
         map.put(AccountColumns.SettingsColumns.CONFIRM_DELETE, settings.confirmDelete ? 1 : 0);
         map.put(
                 AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, settings.confirmArchive ? 1 : 0);
diff --git a/src/com/android/mail/providers/AllAccountObserver.java b/src/com/android/mail/providers/AllAccountObserver.java
new file mode 100644
index 0000000..50ce259
--- /dev/null
+++ b/src/com/android/mail/providers/AllAccountObserver.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2013 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.providers;
+
+import com.android.mail.ui.AccountController;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
+
+import android.database.DataSetObserver;
+
+/**
+ * A simple extension of {@link android.database.DataSetObserver} to provide all Accounts in
+ * {@link #onChanged(Account[])} when the list of Accounts changes. Initializing the object
+ * registers with the observer with the {@link com.android.mail.ui.AccountController} provided.
+ * The object will then begin to receive {@link #onChanged(Account[])} till {@link
+ * #unregisterAndDestroy()} is called. <p> To implement an {@link com.android.mail.providers
+ * .AllAccountObserver}, you need to implement the {@link #onChanged(Account[])} method.
+ */
+public abstract class AllAccountObserver extends DataSetObserver {
+    /**
+     * The AccountController that the observer is registered with.
+     */
+    private AccountController mController;
+
+    private static final String LOG_TAG = LogTag.getLogTag();
+
+    /**
+     * The no-argument constructor leaves the object unusable till
+     * {@link #initialize(com.android.mail.ui.AccountController)} is called.
+     */
+    public AllAccountObserver() {
+    }
+
+    /**
+     * Initializes an {@link com.android.mail.providers.AllAccountObserver} object that receives
+     * a call to {@link #onChanged(Account[])} when the controller changes the list of accounts.
+     *
+     * @param controller
+     */
+    public Account[] initialize(AccountController controller) {
+        if (controller == null) {
+            LogUtils.wtf(LOG_TAG, "AllAccountObserver initialized with null controller!");
+        }
+        mController = controller;
+        mController.registerAllAccountObserver(this);
+        return mController.getAllAccounts();
+    }
+
+    @Override
+    public final void onChanged() {
+        if (mController == null) {
+            return;
+        }
+        onChanged(mController.getAllAccounts());
+    }
+
+    /**
+     * Callback invoked when the list of Accounts changes.
+     * The updated list is passed as the argument.
+     * @param allAccounts the array of all accounts in the current application.
+     */
+    public abstract void onChanged(Account[] allAccounts);
+
+    /**
+     * Return the array of existing accounts.
+     * @return the array of existing accounts.
+     */
+    public final Account[] getAllAccounts() {
+        if (mController == null) {
+            return null;
+        }
+        return mController.getAllAccounts();
+    }
+
+    /**
+     * Unregisters for list of Account changes and makes the object unusable.
+     */
+    public void unregisterAndDestroy() {
+        if (mController == null) {
+            return;
+        }
+        mController.unregisterAllAccountObserver(this);
+    }
+}
diff --git a/src/com/android/mail/providers/Folder.java b/src/com/android/mail/providers/Folder.java
index a34786d..928d6bb 100644
--- a/src/com/android/mail/providers/Folder.java
+++ b/src/com/android/mail/providers/Folder.java
@@ -18,7 +18,6 @@
 package com.android.mail.providers;
 
 import android.content.Context;
-import android.content.CursorLoader;
 import android.database.Cursor;
 import android.graphics.drawable.PaintDrawable;
 import android.net.Uri;
@@ -176,6 +175,11 @@
      */
     public Folder parent;
 
+    /**
+     * The time at which the last message was received.
+     */
+    public long lastMessageTimestamp;
+
     /** An immutable, empty conversation list */
     public static final Collection<Folder> EMPTY = Collections.emptyList();
 
@@ -184,7 +188,8 @@
             boolean hasChildren, int syncWindow, Uri conversationListUri, Uri childFoldersListUri,
             int unseenCount, int unreadCount, int totalCount, Uri refreshUri, int syncStatus,
             int lastSyncResult, int type, int iconResId, int notificationIconResId, String bgColor,
-            String fgColor, Uri loadMoreUri, String hierarchicalDesc, Folder parent) {
+            String fgColor, Uri loadMoreUri, String hierarchicalDesc, Folder parent,
+            final long lastMessageTimestamp) {
         this.id = id;
         this.persistentId = persistentId;
         this.uri = uri;
@@ -208,6 +213,7 @@
         this.loadMoreUri = loadMoreUri;
         this.hierarchicalDesc = hierarchicalDesc;
         this.parent = parent;
+        this.lastMessageTimestamp = lastMessageTimestamp;
     }
 
     public Folder(Cursor cursor) {
@@ -240,6 +246,7 @@
         loadMoreUri = !TextUtils.isEmpty(loadMore) ? Uri.parse(loadMore) : null;
         hierarchicalDesc = cursor.getString(UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN);
         parent = null;
+        lastMessageTimestamp = cursor.getLong(UIProvider.FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN);
     }
 
     /**
@@ -282,6 +289,7 @@
         loadMoreUri = in.readParcelable(loader);
         hierarchicalDesc = in.readString();
         parent = in.readParcelable(loader);
+        lastMessageTimestamp = in.readLong();
      }
 
     @Override
@@ -310,6 +318,7 @@
         dest.writeParcelable(loadMoreUri, 0);
         dest.writeString(hierarchicalDesc);
         dest.writeParcelable(parent, 0);
+        dest.writeLong(lastMessageTimestamp);
     }
 
     /**
@@ -625,6 +634,7 @@
         f.name = cursor.getString(UIProvider.FOLDER_NAME_COLUMN);
         f.iconResId = cursor.getInt(UIProvider.FOLDER_ICON_RES_ID_COLUMN);
         f.notificationIconResId = cursor.getInt(UIProvider.FOLDER_NOTIFICATION_ICON_RES_ID_COLUMN);
+        f.lastMessageTimestamp = cursor.getLong(UIProvider.FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN);
         return f;
     }
 }
diff --git a/src/com/android/mail/providers/FolderObserver.java b/src/com/android/mail/providers/FolderObserver.java
new file mode 100644
index 0000000..03c1ac8
--- /dev/null
+++ b/src/com/android/mail/providers/FolderObserver.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013 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.providers;
+
+import com.android.mail.ui.FolderController;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
+
+import android.database.DataSetObserver;
+
+/**
+ * A simple extension of {@link android.database.DataSetObserver} to provide the updated Folder in
+ * {@link #onChanged(Folder)} when the Folder changes. Initializing the object registers with
+ * the observer with the {@link com.android.mail.ui.FolderController} provided. The object will then begin to
+ * receive {@link #onChanged(Folder)} till {@link #unregisterAndDestroy()} is called.
+ * <p>
+ * To implement an {@link FolderObserver}, you need to implement the {@link #onChanged(Folder)}
+ * method.
+ */
+public abstract class FolderObserver extends DataSetObserver {
+    /**
+     * The FolderController that the observer is registered with.
+     */
+    private FolderController mController;
+
+    private static final String LOG_TAG = LogTag.getLogTag();
+
+    /**
+     * The no-argument constructor leaves the object unusable till
+     * {@link #initialize(FolderController)} is called.
+     */
+    public FolderObserver () {
+    }
+
+    /**
+     * Initializes an {@link FolderObserver} object that receives a call to
+     * {@link #onChanged(Folder)} when the controller changes the Folder.
+     *
+     * @param controller
+     */
+    public Folder initialize(FolderController controller) {
+        if (controller == null) {
+            LogUtils.wtf(LOG_TAG, "FolderObserver initialized with null controller!");
+        }
+        mController = controller;
+        mController.registerFolderObserver(this);
+        return mController.getFolder();
+    }
+
+    @Override
+    public final void onChanged() {
+        if (mController == null) {
+            return;
+        }
+        onChanged(mController.getFolder());
+    }
+
+    /**
+     * Callback invoked when the Folder object is changed.  Since {@link Folder} objects are
+     * immutable, updates can be received on changes to individual settings (sync on/off)
+     * in addition to changes of Folders: alice@example.com -> bob@example.com.
+     * The updated Folder is passed as the argument.
+     * @param newFolder
+     */
+    public abstract void onChanged(Folder newFolder);
+
+    /**
+     * Return the current folder.
+     * @return
+     */
+    public final Folder getFolder() {
+        if (mController == null) {
+            return null;
+        }
+        return mController.getFolder();
+    }
+
+    /**
+     * Unregisters for Folder changes and makes the object unusable.
+     */
+    public void unregisterAndDestroy() {
+        if (mController == null) {
+            return;
+        }
+        mController.unregisterFolderObserver(this);
+    }
+}
diff --git a/src/com/android/mail/providers/MailAppProvider.java b/src/com/android/mail/providers/MailAppProvider.java
index 92360c3..23c8965 100644
--- a/src/com/android/mail/providers/MailAppProvider.java
+++ b/src/com/android/mail/providers/MailAppProvider.java
@@ -27,18 +27,18 @@
 import android.content.Loader;
 import android.content.Loader.OnLoadCompleteListener;
 import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.net.Uri;
 import android.os.Bundle;
 
+import com.android.mail.R;
 import com.android.mail.providers.UIProvider.AccountCursorExtraKeys;
-import com.android.mail.providers.protos.boot.AccountReceiver;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.MatrixCursorWithExtra;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
@@ -86,7 +86,6 @@
     private ContentResolver mResolver;
     private static String sAuthority;
     private static MailAppProvider sInstance;
-    private final static Set<Uri> PENDING_ACCOUNT_URIS = Sets.newHashSet();
 
     private volatile boolean mAccountsFullyLoaded = false;
 
@@ -141,24 +140,19 @@
     @Override
     public boolean onCreate() {
         sAuthority = getAuthority();
+        sInstance = this;
         mResolver = getContext().getContentResolver();
 
-        final Intent intent = new Intent(AccountReceiver.ACTION_PROVIDER_CREATED);
-        getContext().sendBroadcast(intent);
-
         // Load the previously saved account list
         loadCachedAccountList();
 
-        synchronized (PENDING_ACCOUNT_URIS) {
-            sInstance = this;
+        final Resources res = getContext().getResources();
+        // Load the uris for the account list
+        final String[] accountQueryUris = res.getStringArray(R.array.account_providers);
 
-            // Handle the case where addAccountsForUriAsync was called before
-            // this Provider instance was created
-            final Set<Uri> urisToQery = ImmutableSet.copyOf(PENDING_ACCOUNT_URIS);
-            PENDING_ACCOUNT_URIS.clear();
-            for (Uri accountQueryUri : urisToQery) {
-                addAccountsForUriAsync(accountQueryUri);
-            }
+        for (String accountQueryUri : accountQueryUris) {
+            final Uri uri = Uri.parse(accountQueryUri);
+            addAccountsForUriAsync(uri);
         }
 
         return true;
@@ -166,9 +160,7 @@
 
     @Override
     public void shutdown() {
-        synchronized (PENDING_ACCOUNT_URIS) {
-            sInstance = null;
-        }
+        sInstance = null;
 
         for (CursorLoader loader : mCursorLoaderMap.values()) {
             loader.stopLoading();
@@ -243,15 +235,8 @@
      * @param resolver
      * @param accountsQueryUri
      */
-    public static void addAccountsForUriAsync(Uri accountsQueryUri) {
-        synchronized (PENDING_ACCOUNT_URIS) {
-            final MailAppProvider instance = getInstance();
-            if (instance != null) {
-                instance.startAccountsLoader(accountsQueryUri);
-            } else {
-                PENDING_ACCOUNT_URIS.add(accountsQueryUri);
-            }
-        }
+    private void addAccountsForUriAsync(Uri accountsQueryUri) {
+        startAccountsLoader(accountsQueryUri);
     }
 
     /**
diff --git a/src/com/android/mail/providers/Message.java b/src/com/android/mail/providers/Message.java
index 750d17d..ff007eb 100644
--- a/src/com/android/mail/providers/Message.java
+++ b/src/com/android/mail/providers/Message.java
@@ -110,7 +110,7 @@
     /**
      * @see UIProvider.MessageColumns#REF_MESSAGE_ID
      */
-    public String refMessageId;
+    public Uri refMessageUri;
     /**
      * @see UIProvider.MessageColumns#DRAFT_TYPE
      */
@@ -227,7 +227,7 @@
         dest.writeString(bodyHtml);
         dest.writeString(bodyText);
         dest.writeInt(embedsExternalResources ? 1 : 0);
-        dest.writeString(refMessageId);
+        dest.writeParcelable(refMessageUri, 0);
         dest.writeInt(draftType);
         dest.writeInt(appendRefMessageContent ? 1 : 0);
         dest.writeInt(hasAttachments ? 1 : 0);
@@ -261,7 +261,7 @@
         bodyHtml = in.readString();
         bodyText = in.readString();
         embedsExternalResources = in.readInt() != 0;
-        refMessageId = in.readString();
+        refMessageUri = in.readParcelable(null);
         draftType = in.readInt();
         appendRefMessageContent = in.readInt() != 0;
         hasAttachments = in.readInt() != 0;
@@ -322,7 +322,10 @@
             bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN);
             embedsExternalResources = cursor
                     .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0;
-            refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN);
+            final String refMessageUriStr =
+                    cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_URI_COLUMN);
+            refMessageUri = !TextUtils.isEmpty(refMessageUriStr) ?
+                    Uri.parse(refMessageUriStr) : null;
             draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN);
             appendRefMessageContent = cursor
                     .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0;
diff --git a/src/com/android/mail/providers/Settings.java b/src/com/android/mail/providers/Settings.java
index a7519f2..6cb7c3a 100644
--- a/src/com/android/mail/providers/Settings.java
+++ b/src/com/android/mail/providers/Settings.java
@@ -66,7 +66,7 @@
     public final int messageTextSize;
     public final int snapHeaders;
     public final int replyBehavior;
-    public final boolean showCheckboxes;
+    public final boolean hideCheckboxes;
     public final boolean confirmDelete;
     public final boolean confirmArchive;
     public final boolean confirmSend;
@@ -101,7 +101,7 @@
         messageTextSize = MessageTextSize.NORMAL;
         snapHeaders = SnapHeaderValue.ALWAYS;
         replyBehavior = DefaultReplyBehavior.REPLY;
-        showCheckboxes = false;
+        hideCheckboxes = false;
         confirmDelete = false;
         confirmArchive = false;
         confirmSend = false;
@@ -122,7 +122,7 @@
         messageTextSize = inParcel.readInt();
         snapHeaders = inParcel.readInt();
         replyBehavior = inParcel.readInt();
-        showCheckboxes = inParcel.readInt() != 0;
+        hideCheckboxes = inParcel.readInt() != 0;
         confirmDelete = inParcel.readInt() != 0;
         confirmArchive = inParcel.readInt() != 0;
         confirmSend = inParcel.readInt() != 0;
@@ -148,8 +148,8 @@
                 cursor.getColumnIndex(UIProvider.AccountColumns.SettingsColumns.SNAP_HEADERS));
         replyBehavior = cursor.getInt(
                 cursor.getColumnIndex(UIProvider.AccountColumns.SettingsColumns.REPLY_BEHAVIOR));
-        showCheckboxes = cursor.getInt(cursor.getColumnIndex(
-                UIProvider.AccountColumns.SettingsColumns.SHOW_CHECKBOXES)) != 0;
+        hideCheckboxes = cursor.getInt(cursor.getColumnIndex(
+                UIProvider.AccountColumns.SettingsColumns.HIDE_CHECKBOXES)) != 0;
         confirmDelete = cursor.getInt(cursor.getColumnIndex(
                 UIProvider.AccountColumns.SettingsColumns.CONFIRM_DELETE)) != 0;
         confirmArchive = cursor.getInt(cursor.getColumnIndex(
@@ -186,8 +186,8 @@
                 sDefault.snapHeaders);
         replyBehavior = json.optInt(AccountColumns.SettingsColumns.REPLY_BEHAVIOR,
                 sDefault.replyBehavior);
-        showCheckboxes = json.optBoolean(AccountColumns.SettingsColumns.SHOW_CHECKBOXES,
-                sDefault.showCheckboxes);
+        hideCheckboxes = json.optBoolean(AccountColumns.SettingsColumns.HIDE_CHECKBOXES,
+                sDefault.hideCheckboxes);
         confirmDelete = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_DELETE,
                 sDefault.confirmDelete);
         confirmArchive = json.optBoolean(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE,
@@ -241,7 +241,7 @@
             json.put(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE, messageTextSize);
             json.put(AccountColumns.SettingsColumns.SNAP_HEADERS, snapHeaders);
             json.put(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, replyBehavior);
-            json.put(AccountColumns.SettingsColumns.SHOW_CHECKBOXES, showCheckboxes);
+            json.put(AccountColumns.SettingsColumns.HIDE_CHECKBOXES, hideCheckboxes);
             json.put(AccountColumns.SettingsColumns.CONFIRM_DELETE, confirmDelete);
             json.put(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, confirmArchive);
             json.put(AccountColumns.SettingsColumns.CONFIRM_SEND, confirmSend);
@@ -311,7 +311,7 @@
         dest.writeInt(messageTextSize);
         dest.writeInt(snapHeaders);
         dest.writeInt(replyBehavior);
-        dest.writeInt(showCheckboxes ? 1 : 0);
+        dest.writeInt(hideCheckboxes ? 1 : 0);
         dest.writeInt(confirmDelete ? 1 : 0);
         dest.writeInt(confirmArchive? 1 : 0);
         dest.writeInt(confirmSend? 1 : 0);
@@ -360,6 +360,19 @@
     }
 
     /**
+     * @return true if {@link UIProvider.ConversationViewMode.OVERVIEW} mode is set. In the event
+     * that the setting is not yet set, fall back to
+     * {@link UIProvider.ConversationViewMode.DEFAULT}.
+     */
+    public boolean isOverviewMode() {
+        final boolean isDefined = (conversationViewMode
+                != UIProvider.ConversationViewMode.UNDEFINED);
+        final int val = (conversationViewMode != UIProvider.ConversationViewMode.UNDEFINED) ?
+                conversationViewMode : UIProvider.ConversationViewMode.DEFAULT;
+        return (val == UIProvider.ConversationViewMode.OVERVIEW);
+    }
+
+    /**
      * Return the swipe setting for the settings provided. It is safe to pass this method
      * a null object. It always returns a valid {@link Swipe} setting.
      * @return the auto advance setting, a constant from {@link Swipe}
@@ -404,7 +417,7 @@
                 && messageTextSize == that.messageTextSize
                 && snapHeaders == that.snapHeaders
                 && replyBehavior == that.replyBehavior
-                && showCheckboxes == that.showCheckboxes
+                && hideCheckboxes == that.hideCheckboxes
                 && confirmDelete == that.confirmDelete
                 && confirmArchive == that.confirmArchive
                 && confirmSend == that.confirmSend
@@ -433,7 +446,7 @@
     private final int calculateHashCode() {
         return super.hashCode()
                 ^ Objects.hashCode(signature, mAutoAdvance, mTransientAutoAdvance, messageTextSize,
-                        snapHeaders, replyBehavior, showCheckboxes, confirmDelete, confirmArchive,
+                        snapHeaders, replyBehavior, hideCheckboxes, confirmDelete, confirmArchive,
                         confirmSend, defaultInbox, forceReplyFromDefault, maxAttachmentSize, swipe,
                         priorityArrowsEnabled, setupIntentUri, conversationViewMode,
                         veiledAddressPattern);
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index 3316bb1..86ab8aa 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -149,7 +149,7 @@
             .put(AccountColumns.SettingsColumns.MESSAGE_TEXT_SIZE, Integer.class)
             .put(AccountColumns.SettingsColumns.SNAP_HEADERS, Integer.class)
             .put(AccountColumns.SettingsColumns.REPLY_BEHAVIOR, Integer.class)
-            .put(AccountColumns.SettingsColumns.SHOW_CHECKBOXES, Integer.class)
+            .put(AccountColumns.SettingsColumns.HIDE_CHECKBOXES, Integer.class)
             .put(AccountColumns.SettingsColumns.CONFIRM_DELETE, Integer.class)
             .put(AccountColumns.SettingsColumns.CONFIRM_ARCHIVE, Integer.class)
             .put(AccountColumns.SettingsColumns.CONFIRM_SEND, Integer.class)
@@ -472,9 +472,9 @@
 
             /**
              * Integer column containing the user's specified checkbox preference. A
-             * non zero value means to show checkboxes.
+             * non zero value means to hide checkboxes.
              */
-            public static final String SHOW_CHECKBOXES = "show_checkboxes";
+            public static final String HIDE_CHECKBOXES = "hide_checkboxes";
 
             /**
              * Integer column containing the user's specified confirm delete preference value.
@@ -614,7 +614,8 @@
         FolderColumns.BG_COLOR,
         FolderColumns.FG_COLOR,
         FolderColumns.LOAD_MORE_URI,
-        FolderColumns.HIERARCHICAL_DESC
+        FolderColumns.HIERARCHICAL_DESC,
+        FolderColumns.LAST_MESSAGE_TIMESTAMP
     };
 
     public static final int FOLDER_ID_COLUMN = 0;
@@ -639,6 +640,7 @@
     public static final int FOLDER_FG_COLOR_COLUMN = 19;
     public static final int FOLDER_LOAD_MORE_URI_COLUMN = 20;
     public static final int FOLDER_HIERARCHICAL_DESC_COLUMN = 21;
+    public static final int FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN = 22;
 
     public static final class FolderType {
         /** A user defined label. */
@@ -828,6 +830,11 @@
          */
         public static final String HIERARCHICAL_DESC = "hierarchicalDesc";
 
+        /**
+         * The timestamp of the last message received in this folder.
+         */
+        public static final String LAST_MESSAGE_TIMESTAMP = "lastMessageTimestamp";
+
         public FolderColumns() {}
     }
 
@@ -1335,7 +1342,7 @@
     public static final int MESSAGE_BODY_HTML_COLUMN = 12;
     public static final int MESSAGE_BODY_TEXT_COLUMN = 13;
     public static final int MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN = 14;
-    public static final int MESSAGE_REF_MESSAGE_ID_COLUMN = 15;
+    public static final int MESSAGE_REF_MESSAGE_URI_COLUMN = 15;
     public static final int MESSAGE_DRAFT_TYPE_COLUMN = 16;
     public static final int MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN = 17;
     public static final int MESSAGE_HAS_ATTACHMENTS_COLUMN = 18;
@@ -1927,6 +1934,7 @@
          * require panning
          */
         public static final int READING = 1;
+        public static final int DEFAULT = OVERVIEW;
     }
 
     public static final class SnapHeaderValue {
diff --git a/src/com/android/mail/providers/protos/mock/MockUiProvider.java b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
index 3cf0f0f..1055b42 100644
--- a/src/com/android/mail/providers/protos/mock/MockUiProvider.java
+++ b/src/com/android/mail/providers/protos/mock/MockUiProvider.java
@@ -387,6 +387,7 @@
 
     @Override
     public boolean onCreate() {
+        MockUiProvider.initializeMockProvider();
         return true;
     }
 
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 8d2ec4c..0f07ef0 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -36,7 +36,6 @@
 import android.content.Intent;
 import android.content.Loader;
 import android.content.res.Resources;
-import android.database.Cursor;
 import android.database.DataSetObservable;
 import android.database.DataSetObserver;
 import android.net.Uri;
@@ -90,6 +89,7 @@
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.NotificationActionUtils;
+import com.android.mail.utils.Observable;
 import com.android.mail.utils.Utils;
 import com.android.mail.utils.VeiledAddressMatcher;
 
@@ -204,25 +204,12 @@
 
     private final Set<Uri> mCurrentAccountUris = Sets.newHashSet();
     protected ConversationCursor mConversationListCursor;
-    private final DataSetObservable mConversationListObservable = new DataSetObservable() {
-        @Override
-        public void registerObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.registerObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.register(List)Observer: %s before=%d after=%d", observer,
-                    count, mObservers.size());
-        }
-        @Override
-        public void unregisterObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.unregisterObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.unregister(List)Observer: %s before=%d after=%d", observer,
-                    count, mObservers.size());
-        }
-    };
+    private final DataSetObservable mConversationListObservable = new Observable("List");
 
     /** Runnable that checks the logging level to enable/disable the logging service. */
     private Runnable mLogServiceChecker = null;
+    /** List of all accounts currently known to the controller. */
+    private Account[] mAllAccounts;
 
     /**
      * Interface for actions that are deferred until after a load completes. This is for handling
@@ -240,40 +227,13 @@
     private RefreshTimerTask mConversationListRefreshTask;
 
     /** Listeners that are interested in changes to the current account. */
-    private final DataSetObservable mAccountObservers = new DataSetObservable() {
-        @Override
-        public void registerObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.registerObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.register(Account)Observer: %s before=%d after=%d",
-                    observer, count, mObservers.size());
-        }
-        @Override
-        public void unregisterObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.unregisterObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.unregister(Account)Observer: %s before=%d after=%d",
-                    observer, count, mObservers.size());
-        }
-    };
-
+    private final DataSetObservable mAccountObservers = new Observable("Account");
     /** Listeners that are interested in changes to the recent folders. */
-    private final DataSetObservable mRecentFolderObservers = new DataSetObservable() {
-        @Override
-        public void registerObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.registerObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.register(RecentFolder)Observer: %s before=%d after=%d",
-                    observer, count, mObservers.size());
-        }
-        @Override
-        public void unregisterObserver(DataSetObserver observer) {
-            final int count = mObservers.size();
-            super.unregisterObserver(observer);
-            LogUtils.d(LOG_TAG, "IN AAC.unregister(RecentFolder)Observer: %s before=%d after=%d",
-                    observer, count, mObservers.size());
-        }
-    };
+    private final DataSetObservable mRecentFolderObservers = new Observable("RecentFolder");
+    /** Listeners that are interested in changes to the list of all accounts. */
+    private final DataSetObservable mAllAccountObservers = new Observable("AllAccounts");
+    /** Listeners that are interested in changes to the current folder. */
+    private final DataSetObservable mFolderObservable = new Observable("CurrentFolder");
 
     /**
      * Selected conversations, if any.
@@ -302,8 +262,6 @@
     /** Object that listens to all LoaderCallbacks that result in {@link Account} creation. */
     private final AccountLoads mAccountCallbacks = new AccountLoads();
 
-    private final DataSetObservable mFolderObservable = new DataSetObservable();
-
     /**
      * Matched addresses that must be shielded from users because they are temporary. Even though
      * this is instantiated from settings, this matcher is valid for all accounts, and is expected
@@ -333,6 +291,13 @@
      * perhaps.
      */
     public static final int LAST_LOADER_ID = 100;
+    /**
+     * Guaranteed to be the last loader ID used by the Fragment. Loaders are owned by Activity or
+     * fragments, and within an activity, loader IDs need to be unique. Currently,
+     * {@link SectionedInboxTeaserView} is the only class that uses the
+     * {@link ConversationListFragment}'s LoaderManager.
+     */
+    public static final int LAST_FRAGMENT_LOADER_ID = 1000;
 
     private static final int ADD_ACCOUNT_REQUEST_CODE = 1;
     private static final int REAUTHENTICATE_REQUEST_CODE = 2;
@@ -500,11 +465,10 @@
         if (actionBar != null && mActionBarView != null) {
             actionBar.setCustomView(mActionBarView, new ActionBar.LayoutParams(
                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-            // Show a custom view and home icon, but remove the title
+            // Show a custom view and home icon, keep the title and subttitle
             final int mask = ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_TITLE
                     | ActionBar.DISPLAY_SHOW_HOME;
-            final int enabled = ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME;
-            actionBar.setDisplayOptions(enabled, mask);
+            actionBar.setDisplayOptions(mask, mask);
             mActionBarView.attach();
         }
         mViewMode.addListener(mActionBarView);
@@ -546,7 +510,7 @@
     }
 
     @Override
-    public void onAccountChanged(Account account) {
+    public void changeAccount(Account account) {
         // Is the account or account settings different from the existing account?
         final boolean firstLoad = mAccount == null;
         final boolean accountChanged = firstLoad || !account.uri.equals(mAccount.uri);
@@ -556,7 +520,7 @@
         }
         // We also don't want to do anything if the new account is null
         if (account == null) {
-            LogUtils.e(LOG_TAG, "AAC.onAccountChanged(null) called.");
+            LogUtils.e(LOG_TAG, "AAC.changeAccount(null) called.");
             return;
         }
         final String accountName = account.name;
@@ -605,6 +569,21 @@
     }
 
     @Override
+    public void registerAllAccountObserver(DataSetObserver observer) {
+        mAllAccountObservers.registerObserver(observer);
+    }
+
+    @Override
+    public void unregisterAllAccountObserver(DataSetObserver observer) {
+        mAllAccountObservers.unregisterObserver(observer);
+    }
+
+    @Override
+    public Account[] getAllAccounts() {
+        return mAllAccounts;
+    }
+
+    @Override
     public Account getAccount() {
         return mAccount;
     }
@@ -1779,8 +1758,10 @@
             }
             // Put the folder and conversation, and ask the loader to create this folder.
             final Bundle args = new Bundle();
-            args.putParcelable(Utils.EXTRA_FOLDER_URI,
-                    intent.getParcelableExtra(Utils.EXTRA_FOLDER_URI));
+            final Uri folderUri = intent.hasExtra(Utils.EXTRA_FOLDER_URI)
+                    ? (Uri) intent.getParcelableExtra(Utils.EXTRA_FOLDER_URI)
+                    : mAccount.settings.defaultInbox;
+            args.putParcelable(Utils.EXTRA_FOLDER_URI, folderUri);
             args.putParcelable(Utils.EXTRA_CONVERSATION,
                     intent.getParcelableExtra(Utils.EXTRA_CONVERSATION));
             restartOptionalLoader(LOADER_FIRST_FOLDER, mFolderCallbacks, args);
@@ -1860,8 +1841,7 @@
             Utils.sConvLoadTimer.start();
         }
 
-        MailLogService.log("AbstractActivityController", "showConversation(" + conversation + " )"
-                + "");
+        MailLogService.log("AbstractActivityController", "showConversation(%s)", conversation);
         // Set the current conversation just in case it wasn't already set.
         setCurrentConversation(conversation);
         // Add the folder that we were viewing to the recent folders list.
@@ -2143,11 +2123,13 @@
             }
         }
         if (accountChanged) {
-            onAccountChanged(newAccount);
+            changeAccount(newAccount);
         }
+
         // Whether we have updated the current account or not, we need to update the list of
         // accounts in the ActionBar.
-        mActionBarView.setAccounts(allAccounts);
+        mAllAccounts = allAccounts;
+        mAllAccountObservers.notifyChanged();
         return (allAccounts.length > 0);
     }
 
@@ -2295,7 +2277,7 @@
                     @Override
                     public void run() {
                         onUndoAvailable(new ToastBarOperation(mTarget.size(), mAction,
-                                ToastBarOperation.UNDO, mIsSelectedSet));
+                                ToastBarOperation.UNDO, mIsSelectedSet, mFolder));
                     }
                 }, mShowUndoBarDelay);
             }
@@ -2322,7 +2304,8 @@
     // conversations to.
     @Override
     public final void assignFolder(Collection<FolderOperation> folderOps,
-            Collection<Conversation> target, boolean batch, boolean showUndo) {
+            Collection<Conversation> target, boolean batch, boolean showUndo,
+            final boolean isMoveTo) {
         // Actions are destructive only when the current folder can be assigned
         // to (which is the same as being able to un-assign a conversation from the folder) and
         // when the list of folders contains the current folder.
@@ -2339,12 +2322,40 @@
         // Update the UI elements depending no their visibility and availability
         // TODO(viki): Consolidate this into a single method requestDelete.
         if (isDestructive) {
+            /*
+             * If this is a MOVE operation, we want the action folder to be the destination folder.
+             * Otherwise, we want it to be the current folder.
+             *
+             * A set of folder operations is a move if there are exactly two operations: an add and
+             * a remove.
+             */
+            final Folder actionFolder;
+            if (folderOps.size() != 2) {
+                actionFolder = mFolder;
+            } else {
+                Folder addedFolder = null;
+                boolean hasRemove = false;
+                for (final FolderOperation folderOperation : folderOps) {
+                    if (folderOperation.mAdd) {
+                        addedFolder = folderOperation.mFolder;
+                    } else {
+                        hasRemove = true;
+                    }
+                }
+
+                if (hasRemove && addedFolder != null) {
+                    actionFolder = addedFolder;
+                } else {
+                    actionFolder = mFolder;
+                }
+            }
+
             folderChange = getDeferredFolderChange(target, folderOps, isDestructive,
-                    batch, showUndo);
+                    batch, showUndo, isMoveTo, actionFolder);
             delete(0, target, folderChange);
         } else {
             folderChange = getFolderChange(target, folderOps, isDestructive,
-                    batch, showUndo);
+                    batch, showUndo, false /* isMoveTo */, mFolder);
             requestUpdate(folderChange);
         }
     }
@@ -2620,8 +2631,9 @@
         }
         // Drag and drop is destructive: we remove conversations from the
         // current folder.
-        final DestructiveAction action = getFolderChange(conversations, dragDropOperations,
-                isDestructive, true, true);
+        final DestructiveAction action =
+                getFolderChange(conversations, dragDropOperations, isDestructive,
+                        true /* isBatch */, true /* showUndo */, true /* isMoveTo */, folder);
         if (isDestructive) {
             delete(0, conversations, action);
         } else {
@@ -2689,7 +2701,7 @@
         @Override
         public void performAction() {
             ToastBarOperation undoOp = new ToastBarOperation(mConversations.size(),
-                    R.id.change_folder, ToastBarOperation.UNDO, true);
+                    R.id.change_folder, ToastBarOperation.UNDO, true /* batch */, mInitialFolder);
             onUndoAvailable(undoOp);
             ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
             ContentValues values = new ContentValues();
@@ -2818,7 +2830,8 @@
                     return loader;
                 case LOADER_RECENT_FOLDERS:
                     LogUtils.d(LOG_TAG, "LOADER_RECENT_FOLDERS created");
-                    if (mAccount != null && mAccount.recentFolderListUri != null) {
+                    if (mAccount != null && mAccount.recentFolderListUri != null
+                            && !mAccount.recentFolderListUri.equals(Uri.EMPTY)) {
                         return new ObjectCursorLoader<Folder>(mContext,
                                 mAccount.recentFolderListUri, everything, Folder.FACTORY);
                     }
@@ -3149,20 +3162,23 @@
         private boolean mIsSelectedSet;
         private boolean mShowUndo;
         private int mAction;
+        private final Folder mActionFolder;
 
         /**
          * Create a new folder destruction object to act on the given conversations.
          * @param target conversations to act upon.
+         * @param actionFolder the {@link Folder} being acted upon, used for displaying the undo bar
          */
         private FolderDestruction(final Collection<Conversation> target,
                 final Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-                boolean showUndo, int action) {
+                boolean showUndo, int action, final Folder actionFolder) {
             mTarget = ImmutableList.copyOf(target);
             mFolderOps.addAll(folders);
             mIsDestructive = isDestructive;
             mIsSelectedSet = isBatch;
             mShowUndo = showUndo;
             mAction = action;
+            mActionFolder = actionFolder;
         }
 
         @Override
@@ -3172,7 +3188,7 @@
             }
             if (mIsDestructive && mShowUndo) {
                 ToastBarOperation undoOp = new ToastBarOperation(mTarget.size(), mAction,
-                        ToastBarOperation.UNDO, mIsSelectedSet);
+                        ToastBarOperation.UNDO, mIsSelectedSet, mActionFolder);
                 onUndoAvailable(undoOp);
             }
             // For each conversation, for each operation, add/ remove the
@@ -3224,18 +3240,18 @@
 
     public final DestructiveAction getFolderChange(Collection<Conversation> target,
             Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-            boolean showUndo) {
+            boolean showUndo, final boolean isMoveTo, final Folder actionFolder) {
         final DestructiveAction da = getDeferredFolderChange(target, folders, isDestructive,
-                isBatch, showUndo);
+                isBatch, showUndo, isMoveTo, actionFolder);
         registerDestructiveAction(da);
         return da;
     }
 
     public final DestructiveAction getDeferredFolderChange(Collection<Conversation> target,
             Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
-            boolean showUndo) {
-        return new FolderDestruction(target, folders, isDestructive, isBatch,
-                showUndo, R.id.change_folder);
+            boolean showUndo, final boolean isMoveTo, final Folder actionFolder) {
+        return new FolderDestruction(target, folders, isDestructive, isBatch, showUndo,
+                isMoveTo ? R.id.move_folder : R.id.change_folder, actionFolder);
     }
 
     @Override
@@ -3245,7 +3261,7 @@
         Collection<FolderOperation> folderOps = new ArrayList<FolderOperation>();
         folderOps.add(new FolderOperation(toRemove, false));
         return new FolderDestruction(target, folderOps, isDestructive, isBatch,
-                showUndo, R.id.remove_folder);
+                showUndo, R.id.remove_folder, mFolder);
     }
 
     @Override
@@ -3332,7 +3348,7 @@
                 false, /* showActionIcon */
                 actionTextResourceId,
                 replaceVisibleToast,
-                new ToastBarOperation(1, 0, ToastBarOperation.ERROR, false));
+                new ToastBarOperation(1, 0, ToastBarOperation.ERROR, false, folder));
     }
 
     private ActionClickedListener getRetryClickedListener(final Folder folder) {
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index 65718cb..ba63588 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -98,7 +98,6 @@
     protected String mBaseUri;
     protected Account mAccount;
     protected final Map<String, Address> mAddressCache = Maps.newHashMap();
-    protected boolean mEnableContentReadySignal;
     private MessageCursor mCursor;
     private Context mContext;
     /**
@@ -203,17 +202,6 @@
         // base uri that us guaranteed to be unique for this conversation.
         mBaseUri = "x-thread://" + mAccount.name + "/" + mConversation.id;
 
-        // On JB or newer, we use the 'webkitAnimationStart' DOM event to signal load complete
-        // Below JB, try to speed up initial render by having the webview do supplemental draws to
-        // custom a software canvas.
-        // TODO(mindyp):
-        //PAGE READINESS SIGNAL FOR JELLYBEAN AND NEWER
-        // Notify the app on 'webkitAnimationStart' of a simple dummy element with a simple no-op
-        // animation that immediately runs on page load. The app uses this as a signal that the
-        // 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 = false; //Utils.isRunningJellybeanOrLater();
         LogUtils.d(LOG_TAG, "onCreate in ConversationViewFragment (this=%s)", this);
         // Not really, we just want to get a crack to store a reference to the change_folder item
         setHasOptionsMenu(true);
diff --git a/src/com/android/mail/ui/AccountChangeListener.java b/src/com/android/mail/ui/AccountChangeListener.java
deleted file mode 100644
index 7690799..0000000
--- a/src/com/android/mail/ui/AccountChangeListener.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- *      Copyright (C) 2012 Google Inc.
- *      Licensed to The Android Open Source Project.
- *
- *      Licensed under the Apache License, Version 2.0 (the "License");
- *      you may not use this file except in compliance with the License.
- *      You may obtain a copy of the License at
- *
- *           http://www.apache.org/licenses/LICENSE-2.0
- *
- *      Unless required by applicable law or agreed to in writing, software
- *      distributed under the License is distributed on an "AS IS" BASIS,
- *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *      See the License for the specific language governing permissions and
- *      limitations under the License.
- *******************************************************************************/
-package com.android.mail.ui;
-
-import com.android.mail.providers.Account;
-
-/**
- * The callback interface for when a list item has been selected.
- */
-public interface AccountChangeListener {
-    /**
-     * Handles selecting a folder from within the {@link FolderListFragment}.
-     *
-     * @param folder the selected folder
-     */
-    void onAccountChanged(Account account);
-}
diff --git a/src/com/android/mail/ui/AccountController.java b/src/com/android/mail/ui/AccountController.java
index e13b2eb..1d7745c 100644
--- a/src/com/android/mail/ui/AccountController.java
+++ b/src/com/android/mail/ui/AccountController.java
@@ -45,9 +45,31 @@
      */
     Account getAccount();
 
+
+    /**
+     * Registers to receive changes to the list of accounts, and obtain the current list.
+     */
+    void registerAllAccountObserver(DataSetObserver observer);
+
+    /**
+     * Removes a listener from receiving account list changes.
+     */
+    void unregisterAllAccountObserver(DataSetObserver observer);
+
+    /** Returns a list of all accounts currently known. */
+    Account[] getAllAccounts();
+
     /**
      * Returns an object that can check veiled addresses.
      * @return
      */
     VeiledAddressMatcher getVeiledAddressMatcher();
+
+    /**
+     * Handles selecting an account from within the {@link FolderListFragment}.
+     *
+     * @param account the account to change to.
+     */
+    void changeAccount(Account account);
+
 }
diff --git a/src/com/android/mail/ui/ActivityController.java b/src/com/android/mail/ui/ActivityController.java
index 5e80e65..d1a1740 100644
--- a/src/com/android/mail/ui/ActivityController.java
+++ b/src/com/android/mail/ui/ActivityController.java
@@ -42,8 +42,7 @@
  */
 public interface ActivityController extends LayoutListener,
         ModeChangeListener, ConversationListCallbacks,
-        FolderChangeListener, AccountChangeListener,
-        ConversationSetObserver, ConversationListener,
+        FolderChangeListener, ConversationSetObserver, ConversationListener,
         FolderListFragment.FolderListSelectionListener, HelpCallback, UndoListener,
         ConversationUpdater, ErrorListener, FolderController, AccountController,
         ConversationPositionTracker.Callbacks, ConversationListFooterView.FooterViewClickListener,
diff --git a/src/com/android/mail/ui/AddableFolderSelectorAdapter.java b/src/com/android/mail/ui/AddableFolderSelectorAdapter.java
index fcf79b0..0888369 100644
--- a/src/com/android/mail/ui/AddableFolderSelectorAdapter.java
+++ b/src/com/android/mail/ui/AddableFolderSelectorAdapter.java
@@ -84,6 +84,8 @@
                             .getString(UIProvider.FOLDER_LOAD_MORE_URI_COLUMN);
                     folder[UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN] = folderCursor
                             .getString(UIProvider.FOLDER_HIERARCHICAL_DESC_COLUMN);
+                    folder[UIProvider.FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN] = folderCursor
+                            .getLong(UIProvider.FOLDER_LAST_MESSAGE_TIMESTAMP_COLUMN);
                     cursor.addRow(folder);
                 }
             } while (folderCursor.moveToNext());
diff --git a/src/com/android/mail/ui/AnimatedAdapter.java b/src/com/android/mail/ui/AnimatedAdapter.java
index 8524c29..0a75711 100644
--- a/src/com/android/mail/ui/AnimatedAdapter.java
+++ b/src/com/android/mail/ui/AnimatedAdapter.java
@@ -24,6 +24,7 @@
 import android.database.Cursor;
 import android.os.Bundle;
 import android.os.Handler;
+import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -49,6 +50,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map.Entry;
 
 public class AnimatedAdapter extends SimpleCursorAdapter implements
@@ -115,6 +117,9 @@
         }
     };
 
+    private final List<ConversationSpecialItemView> mSpecialViews;
+    private final SparseArray<ConversationSpecialItemView> mSpecialViewPositions;
+
     private final void setAccount(Account newAccount) {
         mAccount = newAccount;
         mPriorityMarkersEnabled = mAccount.settings.priorityArrowsEnabled;
@@ -130,6 +135,12 @@
     public AnimatedAdapter(Context context, ConversationCursor cursor,
             ConversationSelectionSet batch, ControllableActivity activity,
             SwipeableListView listView) {
+        this(context, cursor, batch, activity, listView, null);
+    }
+
+    public AnimatedAdapter(Context context, ConversationCursor cursor,
+            ConversationSelectionSet batch, ControllableActivity activity,
+            SwipeableListView listView, final List<ConversationSpecialItemView> specialViews) {
         super(context, -1, cursor, UIProvider.CONVERSATION_PROJECTION, null, 0);
         mContext = context;
         mBatchConversations = batch;
@@ -146,6 +157,16 @@
                     context.getResources()
                         .getInteger(R.integer.dismiss_all_leavebehinds_long_delay);
         }
+        mSpecialViews =
+                specialViews == null ? new ArrayList<ConversationSpecialItemView>(0)
+                        : new ArrayList<ConversationSpecialItemView>(specialViews);
+        mSpecialViewPositions = new SparseArray<ConversationSpecialItemView>(mSpecialViews.size());
+
+        for (final ConversationSpecialItemView view : mSpecialViews) {
+            view.setAdapter(this);
+        }
+
+        updateSpecialViews();
     }
 
     public void cancelDismissCounter() {
@@ -169,7 +190,10 @@
 
     @Override
     public int getCount() {
-        final int count = super.getCount();
+        // mSpecialViewPositions only contains the views that are currently being displayed
+        final int specialViewCount = mSpecialViewPositions.size();
+
+        final int count = super.getCount() + specialViewCount;
         return mShowFooter ? count + 1 : count;
     }
 
@@ -211,7 +235,7 @@
             view = new SwipeableConversationItemView(context, mAccount.name);
         }
         view.bind(conv, mActivity, mBatchConversations, mFolder,
-                mAccount != null ? !mAccount.settings.showCheckboxes : false, mSwipeEnabled,
+                mAccount != null ? mAccount.settings.hideCheckboxes : false, mSwipeEnabled,
                 mPriorityMarkersEnabled, this);
         return view;
     }
@@ -231,7 +255,7 @@
     @Override
     public int getItemViewType(int position) {
         // Try to recycle views.
-        if (mShowFooter && position == super.getCount()) {
+        if (mShowFooter && position == getCount() - 1) {
             return TYPE_VIEW_FOOTER;
         } else if (hasLeaveBehinds() || isAnimating()) {
             // Setting as type -1 means the recycler won't take this view and
@@ -241,6 +265,9 @@
             // types. In a future release, use position/id map to try to make
             // this cleaner / faster to determine if the view is animating.
             return TYPE_VIEW_DONT_RECYCLE;
+        } else if (mSpecialViewPositions.get(position) != null) {
+            // Don't recycle the special views
+            return TYPE_VIEW_DONT_RECYCLE;
         }
         return TYPE_VIEW_CONVERSATION;
     }
@@ -306,9 +333,16 @@
 
     @Override
     public View getView(int position, View convertView, ViewGroup parent) {
-        if (mShowFooter && position == super.getCount()) {
+        if (mShowFooter && position == getCount() - 1) {
             return mFooter;
         }
+
+        // Check if this is a special view
+        final View specialView = (View) mSpecialViewPositions.get(position);
+        if (specialView != null) {
+            return specialView;
+        }
+
         ConversationCursor cursor = (ConversationCursor) getItem(position);
         final Conversation conv = cursor.getConversation();
         if (isPositionUndoing(conv.id)) {
@@ -347,6 +381,7 @@
                 return fadeIn;
             }
         }
+
         if (convertView != null && !(convertView instanceof SwipeableConversationItemView)) {
             LogUtils.w(LOG_TAG, "Incorrect convert view received; nulling it out");
             convertView = newView(mContext, cursor, parent);
@@ -497,10 +532,11 @@
 
     @Override
     public long getItemId(int position) {
-        if (mShowFooter && position == super.getCount()) {
+        if (mShowFooter && position == getCount() - 1
+                || mSpecialViewPositions.get(position) != null) {
             return -1;
         }
-        return super.getItemId(position);
+        return super.getItemId(position - getPositionOffset(position));
     }
 
     private View getDeletingView(int position, Conversation conversation, ViewGroup parent,
@@ -541,7 +577,7 @@
             return;
         }
         ((SwipeableConversationItemView) view).bind(cursor, mActivity, mBatchConversations, mFolder,
-                mAccount != null ? !mAccount.settings.showCheckboxes : false,
+                mAccount != null ? mAccount.settings.hideCheckboxes : false,
                         mSwipeEnabled, mPriorityMarkersEnabled, this);
     }
 
@@ -551,7 +587,7 @@
                 position, null, parent);
         view.reset();
         view.bind(conversation, mActivity, mBatchConversations, mFolder,
-                mAccount != null ? !mAccount.settings.showCheckboxes : false, mSwipeEnabled,
+                mAccount != null ? mAccount.settings.hideCheckboxes : false, mSwipeEnabled,
                 mPriorityMarkersEnabled, this);
         mAnimatingViews.put(conversation.id, view);
         return view;
@@ -559,10 +595,12 @@
 
     @Override
     public Object getItem(int position) {
-        if (mShowFooter && position == super.getCount()) {
+        if (mShowFooter && position == getCount() - 1) {
             return mFooter;
+        } else if (mSpecialViewPositions.get(position) != null) {
+            return mSpecialViewPositions.get(position);
         }
-        return super.getItem(position);
+        return super.getItem(position - getPositionOffset(position));
     }
 
     private boolean isPositionDeleting(long id) {
@@ -797,4 +835,67 @@
             item.cancelFadeOutText();
         }
     }
+
+    private void updateSpecialViews() {
+        mSpecialViewPositions.clear();
+
+        for (int i = 0; i < mSpecialViews.size(); i++) {
+            final ConversationSpecialItemView specialView = mSpecialViews.get(i);
+            specialView.onUpdate(mAccount.name, mFolder, getConversationCursor());
+
+            if (specialView.getShouldDisplayInList()) {
+                mSpecialViewPositions.put(specialView.getPosition(), specialView);
+            }
+        }
+    }
+
+    @Override
+    public void notifyDataSetChanged() {
+        updateSpecialViews();
+        super.notifyDataSetChanged();
+    }
+
+    @Override
+    public void changeCursor(final Cursor cursor) {
+        super.changeCursor(cursor);
+        updateSpecialViews();
+    }
+
+    @Override
+    public void changeCursorAndColumns(final Cursor c, final String[] from, final int[] to) {
+        super.changeCursorAndColumns(c, from, to);
+        updateSpecialViews();
+    }
+
+    @Override
+    public Cursor swapCursor(final Cursor c) {
+        final Cursor oldCursor = super.swapCursor(c);
+        updateSpecialViews();
+
+        return oldCursor;
+    }
+
+    /**
+     * Gets the offset for the given position in the underlying cursor, based on any special views
+     * that may be above it.
+     */
+    public int getPositionOffset(final int position) {
+        int offset = 0;
+
+        for (int i = 0; i < mSpecialViewPositions.size(); i++) {
+            final int key = mSpecialViewPositions.keyAt(i);
+            final ConversationSpecialItemView specialView = mSpecialViewPositions.get(key);
+            if (specialView.getPosition() <= position) {
+                offset++;
+            }
+        }
+
+        return offset;
+    }
+
+    public void cleanup() {
+        for (final ConversationSpecialItemView view : mSpecialViews) {
+            view.cleanup();
+        }
+    }
 }
diff --git a/src/com/android/mail/ui/ControllableActivity.java b/src/com/android/mail/ui/ControllableActivity.java
index 37e70f5..f4a1d87 100644
--- a/src/com/android/mail/ui/ControllableActivity.java
+++ b/src/com/android/mail/ui/ControllableActivity.java
@@ -116,4 +116,9 @@
     void stopDragMode();
 
     boolean isAccessibilityEnabled();
+
+    /**
+     * Gets a helper to provide addition features in the conversation list. This may be null.
+     */
+    ConversationListHelper getConversationListHelper();
 }
diff --git a/src/com/android/mail/ui/ConversationListFragment.java b/src/com/android/mail/ui/ConversationListFragment.java
index d1d1153..12d2087 100644
--- a/src/com/android/mail/ui/ConversationListFragment.java
+++ b/src/com/android/mail/ui/ConversationListFragment.java
@@ -43,6 +43,7 @@
 import com.android.mail.providers.AccountObserver;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.Folder;
+import com.android.mail.providers.FolderObserver;
 import com.android.mail.providers.Settings;
 import com.android.mail.providers.UIProvider;
 import com.android.mail.providers.UIProvider.AccountCapabilities;
@@ -57,6 +58,7 @@
 import com.android.mail.utils.Utils;
 
 import java.util.Collection;
+import java.util.List;
 
 /**
  * The conversation list UI component.
@@ -117,7 +119,7 @@
     private ConversationListFooterView mFooterView;
     private View mEmptyView;
     private ErrorListener mErrorListener;
-    private DataSetObserver mFolderObserver;
+    private FolderObserver mFolderObserver;
     private DataSetObserver mConversationCursorObserver;
 
     private ConversationSelectionSet mSelectedSet;
@@ -140,21 +142,6 @@
         super();
     }
 
-    // update the pager title strip as the Folder's conversation count changes
-    private class FolderObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            if (mActivity == null) {
-                return;
-            }
-            final FolderController controller = mActivity.getFolderController();
-            if (controller == null) {
-                return;
-            }
-            onFolderUpdated(controller.getFolder());
-        }
-    }
-
     private class ConversationCursorObserver extends DataSetObserver {
         @Override
         public void onChanged() {
@@ -264,15 +251,32 @@
                 null);
         mFooterView.setClickListener(mActivity);
         final ConversationCursor conversationCursor = getConversationListCursor();
-        mListAdapter = new AnimatedAdapter(mActivity.getApplicationContext(),
-                conversationCursor, mActivity.getSelectedSet(), mActivity, mListView);
+
+        final ConversationListHelper helper = mActivity.getConversationListHelper();
+        final List<ConversationSpecialItemView> specialItemViews =
+                helper != null ? helper.makeConversationListSpecialViews(getActivity(), mAccount,
+                        mActivity.getFolderListSelectionListener()) : null;
+        if (specialItemViews != null) {
+            // Attach to the LoaderManager
+            for (final ConversationSpecialItemView view : specialItemViews) {
+                view.bindLoaderManager(getLoaderManager());
+            }
+        }
+
+        mListAdapter = new AnimatedAdapter(mActivity.getApplicationContext(), conversationCursor,
+                        mActivity.getSelectedSet(), mActivity, mListView, specialItemViews);
         mListAdapter.addFooter(mFooterView);
         mListView.setAdapter(mListAdapter);
         mSelectedSet = mActivity.getSelectedSet();
         mListView.setSelectionSet(mSelectedSet);
         mListAdapter.hideFooter();
-        mFolderObserver = new FolderObserver();
-        mActivity.getFolderController().registerFolderObserver(mFolderObserver);
+        mFolderObserver = new FolderObserver(){
+            @Override
+            public void onChanged(Folder newFolder) {
+                onFolderUpdated(newFolder);
+            }
+        };
+        mFolderObserver.initialize(mActivity.getFolderController());
         mConversationCursorObserver = new ConversationCursorObserver();
         mUpdater = mActivity.getConversationUpdater();
         mUpdater.registerConversationListObserver(mConversationCursorObserver);
@@ -438,7 +442,7 @@
 
         mActivity.unsetViewModeListener(this);
         if (mFolderObserver != null) {
-            mActivity.getFolderController().unregisterFolderObserver(mFolderObserver);
+            mFolderObserver.unregisterAndDestroy();
             mFolderObserver = null;
         }
         if (mConversationCursorObserver != null) {
@@ -446,6 +450,7 @@
             mConversationCursorObserver = null;
         }
         mAccountObserver.unregisterAndDestroy();
+        getAnimatedAdapter().cleanup();
         super.onDestroyView();
     }
 
@@ -475,7 +480,7 @@
     public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
         // Ignore anything that is not a conversation item. Could be a footer.
         if (!(view instanceof ConversationItemView)) {
-            return true;
+            return false;
         }
         ((ConversationItemView) view).toggleCheckMarkOrBeginDrag();
         return true;
@@ -506,7 +511,7 @@
         if (!(view instanceof ToggleableItem)) {
             return;
         }
-        if (!mAccount.settings.showCheckboxes && !mSelectedSet.isEmpty()) {
+        if (mAccount.settings.hideCheckboxes && !mSelectedSet.isEmpty()) {
             ToggleableItem v = (ToggleableItem) view;
             v.toggleCheckMarkOrBeginDrag();
         } else {
@@ -584,30 +589,40 @@
 
     /**
      * View the message at the given position.
-     * @param position
+     *
+     * @param position The position of the conversation in the list (as opposed to its position in
+     *        the cursor)
      */
-    protected void viewConversation(int position) {
+    protected void viewConversation(final int position) {
         LogUtils.d(LOG_TAG, "ConversationListFragment.viewConversation(%d)", position);
-        setSelected(position, true);
-        final ConversationCursor cursor = getConversationListCursor();
-        if (cursor != null && cursor.moveToPosition(position)) {
-            final Conversation conv = new Conversation(cursor);
-            conv.position = position;
-            mCallbacks.onConversationSelected(conv, false /* inLoaderCallbacks */);
-        }
+
+        final ConversationCursor cursor =
+                (ConversationCursor) getAnimatedAdapter().getItem(position);
+        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 */);
     }
 
     /**
      * Sets the selected conversation to the position given here.
-     * @param position
+     * @param position The position of the conversation in the cursor (as opposed to in the list)
      * @param different if the currently selected conversation is different from the one provided
      * here.  This is a difference in conversations, not a difference in positions. For example, a
      * conversation at position 2 can move to position 4 as a result of new mail.
      */
-    public void setSelected(int position, boolean different) {
+    public void setSelected(final int cursorPosition, boolean different) {
         if (mListView.getChoiceMode() == ListView.CHOICE_MODE_NONE) {
             return;
         }
+
+        final int position =
+                cursorPosition + getAnimatedAdapter().getPositionOffset(cursorPosition);
+
         if (different) {
             mListView.smoothScrollToPosition(position);
         }
@@ -775,6 +790,11 @@
             mListAdapter.notifyDataSetChanged();
         }
         mConversationCursorHash = newCursorHash;
+
+        if (newCursor != null) {
+            newCursor.markContentsSeen();
+        }
+
         // If a current conversation is available, and none is selected in the list, then ask
         // the list to select the current conversation.
         final Conversation conv = mCallbacks.getCurrentConversation();
diff --git a/src/com/android/mail/ui/ConversationListHelper.java b/src/com/android/mail/ui/ConversationListHelper.java
new file mode 100644
index 0000000..8470be1
--- /dev/null
+++ b/src/com/android/mail/ui/ConversationListHelper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 Google Inc.
+ * Licensed to The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.mail.ui;
+
+import android.content.Context;
+
+import com.android.mail.providers.Account;
+import com.android.mail.ui.FolderListFragment.FolderListSelectionListener;
+
+import java.util.List;
+
+public interface ConversationListHelper {
+    /**
+     * Creates a list of newly created special views.
+     */
+    List<ConversationSpecialItemView> makeConversationListSpecialViews(Context context,
+            Account account, FolderListSelectionListener listener);
+}
diff --git a/src/com/android/mail/ui/ConversationSpecialItemView.java b/src/com/android/mail/ui/ConversationSpecialItemView.java
new file mode 100644
index 0000000..8488162
--- /dev/null
+++ b/src/com/android/mail/ui/ConversationSpecialItemView.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 Google Inc.
+ * Licensed to The Android Open Source Project.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.mail.ui;
+
+import android.app.LoaderManager;
+import android.widget.BaseAdapter;
+
+import com.android.mail.browse.ConversationCursor;
+import com.android.mail.providers.Folder;
+
+/**
+ * An interface for a view that can be inserted into an {@link AnimatedAdapter} at an arbitrary
+ * point. The methods described here control whether the view gets displayed, and what it displays.
+ */
+public interface ConversationSpecialItemView {
+    /**
+     * Called when there as an update to the information being displayed.
+     *
+     * @param cursor The {@link ConversationCursor}. May be <code>null</code>
+     */
+    void onUpdate(String account, Folder folder, ConversationCursor cursor);
+
+    boolean getShouldDisplayInList();
+
+    int getPosition();
+
+    void setAdapter(BaseAdapter adapter);
+
+    void bindLoaderManager(LoaderManager loaderManager);
+
+    /**
+     * Called when the view is being destroyed.
+     */
+    void cleanup();
+}
diff --git a/src/com/android/mail/ui/ConversationUpdater.java b/src/com/android/mail/ui/ConversationUpdater.java
index fe7f621..55511ac 100644
--- a/src/com/android/mail/ui/ConversationUpdater.java
+++ b/src/com/android/mail/ui/ConversationUpdater.java
@@ -23,7 +23,6 @@
 
 import com.android.mail.browse.ConfirmDialogFragment;
 import com.android.mail.browse.ConversationCursor;
-import com.android.mail.browse.ConversationItemView;
 import com.android.mail.browse.MessageCursor.ConversationMessage;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.ConversationInfo;
@@ -142,15 +141,17 @@
             boolean showUndo);
 
     /**
-     * Assign the target conversations to the given folders, and remove them from all other
-     * folders that they might be assigned to.
+     * Assign the target conversations to the given folders, and remove them from all other folders
+     * that they might be assigned to.
      * @param folders the folders to assign the conversations to.
      * @param target the conversations to act upon.
      * @param batch whether this is a batch operation
      * @param showUndo whether to show the undo bar
+     * @param isMoveTo <code>true</code> if this is a move operation, <code>false</code> if it is
+     *        some other type of folder change operation
      */
     public void assignFolder(Collection<FolderOperation> folders, Collection<Conversation> target,
-            boolean batch, boolean showUndo);
+            boolean batch, boolean showUndo, boolean isMoveTo);
 
     /**
      * Refreshes the conversation list, if one exists.
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index e73c380..8aae3f3 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -83,10 +83,12 @@
 import com.android.mail.utils.LogUtils;
 import com.android.mail.utils.Utils;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 
@@ -193,6 +195,8 @@
 
     private long mWebViewLoadStartMs;
 
+    private final Map<String, String> mMessageTransforms = Maps.newHashMap();
+
     private final DataSetObserver mLoadedObserver = new DataSetObserver() {
         @Override
         public void onChanged() {
@@ -785,10 +789,11 @@
 
         mWebView.getSettings().setBlockNetworkImage(!allowNetworkImages);
 
+        final MailPrefs prefs = MailPrefs.get(getContext());
         // 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),
-                MailPrefs.get(getContext()).shouldMungeTables());
+                prefs.shouldMungeTables(), prefs.shouldMungeImages());
     }
 
     private void renderSuperCollapsedBlock(int start, int end) {
@@ -960,6 +965,18 @@
                 "javascript:unblockImages(['%s']);", TextUtils.join("','", messageDomIds));
         mWebView.loadUrl(url);
     }
+
+    @Override
+    public boolean supportsMessageTransforms() {
+        return true;
+    }
+
+    @Override
+    public String getMessageTransforms(final Message msg) {
+        final String domId = mTemplates.getMessageDomId(msg);
+        return (domId == null) ? null : mMessageTransforms.get(domId);
+    }
+
     // END message header callbacks
 
     @Override
@@ -1025,7 +1042,7 @@
     }
 
     private static boolean isOverviewMode(Account acct) {
-        return acct.settings.conversationViewMode == UIProvider.ConversationViewMode.OVERVIEW;
+        return acct.settings.isOverviewMode();
     }
 
     private void setupOverviewMode() {
@@ -1216,6 +1233,13 @@
                 return 0f;
             }
         }
+
+        @SuppressWarnings("unused")
+        @JavascriptInterface
+        public void onMessageTransform(String messageDomId, String transformText) {
+            LogUtils.i(LOG_TAG, "TRANSFORM: (%s) %s", messageDomId, transformText);
+            mMessageTransforms.put(messageDomId, transformText);
+        }
     }
 
     /**
@@ -1648,7 +1672,7 @@
             mTemplates.appendMessageHtml(msgItem.getMessage(), true /* expanded */,
                     safeForImages, 0, 0);
             final String html = mTemplates.endConversation(mBaseUri,
-                    mConversation.getBaseUri(mBaseUri), 0, 0, false, false, false);
+                    mConversation.getBaseUri(mBaseUri), 0, 0, false, false, false, false);
 
             mMessageView.loadDataWithBaseURL(mBaseUri, html, "text/html", "utf-8", null);
             mMessageViewLoadStartMs = SystemClock.uptimeMillis();
diff --git a/src/com/android/mail/ui/FolderItemView.java b/src/com/android/mail/ui/FolderItemView.java
index 6281339..8235602 100644
--- a/src/com/android/mail/ui/FolderItemView.java
+++ b/src/com/android/mail/ui/FolderItemView.java
@@ -20,6 +20,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.mail.providers.Account;
 import com.android.mail.providers.Folder;
 import com.android.mail.providers.UIProvider.FolderType;
 import com.android.mail.utils.LogTag;
@@ -131,10 +132,20 @@
         }
     }
 
+    public void bind(Account account, DropHandler dropHandler, int count) {
+        mFolder = null;
+        mDropHandler = dropHandler;
+        mFolderTextView.setText(account.name);
+        mFolderParentIcon.setVisibility(View.GONE);
+        mUnreadCountTextView.setVisibility(View.GONE);
+        setUnseenCount(Color.BLACK, 0);
+        setUnreadCount(count);
+    }
+
     /**
      * Sets the unread count, taking care to hide/show the textview if the count is zero/non-zero.
      */
-    private final void setUnreadCount(int count) {
+    private void setUnreadCount(int count) {
         mUnreadCountTextView.setVisibility(count > 0 ? View.VISIBLE : View.GONE);
         if (count > 0) {
             mUnreadCountTextView.setText(Utils.getUnreadCountString(getContext(), count));
@@ -144,7 +155,7 @@
     /**
      * Sets the unseen count, taking care to hide/show the textview if the count is zero/non-zero.
      */
-    private final void setUnseenCount(final int color, final int count) {
+    private void setUnseenCount(final int color, final int count) {
         mUnseenCountTextView.setVisibility(count > 0 ? View.VISIBLE : View.GONE);
         if (count > 0) {
             mUnseenCountTextView.setBackgroundColor(color);
diff --git a/src/com/android/mail/ui/FolderListFragment.java b/src/com/android/mail/ui/FolderListFragment.java
index ca80106..fed9da4 100644
--- a/src/com/android/mail/ui/FolderListFragment.java
+++ b/src/com/android/mail/ui/FolderListFragment.java
@@ -34,12 +34,10 @@
 import android.widget.ImageView;
 import android.widget.ListAdapter;
 import android.widget.ListView;
-import android.widget.TextView;
 
 import com.android.mail.R;
-import com.android.mail.providers.Folder;
-import com.android.mail.providers.RecentFolderObserver;
-import com.android.mail.providers.UIProvider;
+import com.android.mail.adapter.DrawerItem;
+import com.android.mail.providers.*;
 import com.android.mail.providers.UIProvider.FolderType;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
@@ -61,10 +59,14 @@
     private Uri mFolderListUri;
     /** True if you want a sectioned FolderList, false otherwise. */
     private boolean mIsSectioned;
+    /** Is the current device using tablet UI (true if 2-pane, false if 1-pane) */
+    private boolean mIsTabletUI;
     /** An {@link ArrayList} of {@link FolderType}s to exclude from displaying. */
     private ArrayList<Integer> mExcludedFolderTypes;
-    /** Callback into the parent */
-    private FolderListSelectionListener mListener;
+    /** Object that changes folders on our behalf. */
+    private FolderListSelectionListener mFolderChanger;
+    /** Object that changes accounts on our behalf */
+    private AccountController mAccountChanger;
 
     /** The currently selected folder (the folder being viewed).  This is never null. */
     private Uri mSelectedFolderUri = Uri.EMPTY;
@@ -77,16 +79,18 @@
     private Folder mParentFolder;
 
     private static final int FOLDER_LOADER_ID = 0;
-    public static final int MODE_DEFAULT = 0;
-    public static final int MODE_PICK = 1;
     /** Key to store {@link #mParentFolder}. */
     private static final String ARG_PARENT_FOLDER = "arg-parent-folder";
     /** Key to store {@link #mFolderListUri}. */
     private static final String ARG_FOLDER_URI = "arg-folder-list-uri";
     /** Key to store {@link #mIsSectioned} */
     private static final String ARG_IS_SECTIONED = "arg-is-sectioned";
+    /** Key to store {@link #mIsTabletUI} */
+    private static final String ARG_IS_TABLET_UI = "arg-is-tablet-ui";
     /** Key to store {@link #mExcludedFolderTypes} */
     private static final String ARG_EXCLUDED_FOLDER_TYPES = "arg-excluded-folder-types";
+    /** Should the {@link FolderListFragment} show less labels to begin with? */
+    private static final boolean ARE_ITEMS_COLLAPSED = true;
 
     private static final String BUNDLE_LIST_STATE = "flf-list-state";
     private static final String BUNDLE_SELECTED_FOLDER = "flf-selected-folder";
@@ -97,31 +101,24 @@
     private View mEmptyView;
     /** Observer to wait for changes to the current folder so we can change the selected folder */
     private FolderObserver mFolderObserver = null;
+    /** Listen for account changes. */
+    private AccountObserver mAccountObserver = null;
+
+    /** Listen to changes to list of all accounts */
+    private AllAccountObserver mAllAccountObserver = null;
     /**
-     * Type of currently selected folder: {@link FolderListAdapter.Item#FOLDER_SYSTEM},
-     * {@link FolderListAdapter.Item#FOLDER_RECENT} or {@link FolderListAdapter.Item#FOLDER_USER}.
+     * Type of currently selected folder: {@link DrawerItem#FOLDER_SYSTEM},
+     * {@link DrawerItem#FOLDER_RECENT} or {@link DrawerItem#FOLDER_USER}.
      */
-    // Setting to NOT_A_FOLDER = leaving uninitialized.
-    private int mSelectedFolderType = FolderListAdapter.Item.NOT_A_FOLDER;
+    // Setting to INERT_HEADER = leaving uninitialized.
+    private int mSelectedFolderType = DrawerItem.INERT_HEADER;
     private Cursor mFutureData;
     private ConversationListCallbacks mConversationListCallback;
+    /** The current account according to the controller */
+    private Account mCurrentAccount;
 
-    /**
-     * Listens to folder changes from the controller and updates state accordingly.
-     */
-    private final class FolderObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            if (mActivity == null) {
-                return;
-            }
-            final FolderController controller = mActivity.getFolderController();
-            if (controller == null) {
-                return;
-            }
-            setSelectedFolder(controller.getFolder());
-        }
-    }
+    /** List of all accounts currently known */
+    private Account[] mAllAccounts;
 
     /**
      * Constructor needs to be public to handle orientation changes and activity lifecycle events.
@@ -133,21 +130,24 @@
     /**
      * Creates a new instance of {@link ConversationListFragment}, initialized
      * to display conversation list context.
-     * @param isSectioned TODO(viki):
+     * @param isSectioned True if sections should be shown for folder list
+     * @param isTabletUI True if two-pane layout, false if not
      */
     public static FolderListFragment newInstance(Folder parentFolder, Uri folderUri,
-            boolean isSectioned) {
-        return newInstance(parentFolder, folderUri, isSectioned, null);
+            boolean isSectioned, boolean isTabletUI) {
+        return newInstance(parentFolder, folderUri, isSectioned, null, isTabletUI);
     }
 
     /**
      * Creates a new instance of {@link ConversationListFragment}, initialized
      * to display conversation list context.
-     * @param isSectioned TODO(viki):
+     * @param isSectioned True if sections should be shown for folder list
      * @param excludedFolderTypes A list of {@link FolderType}s to exclude from displaying
+     * @param isTabletUI True if two-pane layout, false if not
      */
     public static FolderListFragment newInstance(Folder parentFolder, Uri folderUri,
-            boolean isSectioned, final ArrayList<Integer> excludedFolderTypes) {
+            boolean isSectioned, final ArrayList<Integer> excludedFolderTypes,
+            boolean isTabletUI) {
         final FolderListFragment fragment = new FolderListFragment();
         final Bundle args = new Bundle();
         if (parentFolder != null) {
@@ -155,6 +155,7 @@
         }
         args.putString(ARG_FOLDER_URI, folderUri.toString());
         args.putBoolean(ARG_IS_SECTIONED, isSectioned);
+        args.putBoolean(ARG_IS_TABLET_UI, isTabletUI);
         if (excludedFolderTypes != null) {
             args.putIntegerArrayList(ARG_EXCLUDED_FOLDER_TYPES, excludedFolderTypes);
         }
@@ -179,14 +180,38 @@
         mConversationListCallback = mActivity.getListHandler();
         final FolderController controller = mActivity.getFolderController();
         // Listen to folder changes in the future
-        mFolderObserver = new FolderObserver();
+        mFolderObserver = new FolderObserver() {
+            @Override
+            public void onChanged(Folder newFolder) {
+                setSelectedFolder(newFolder);
+            }
+        };
         if (controller != null) {
             // Only register for selected folder updates if we have a controller.
-            controller.registerFolderObserver(mFolderObserver);
-            mCurrentFolderForUnreadCheck = controller.getFolder();
+            mCurrentFolderForUnreadCheck = mFolderObserver.initialize(controller);
+        }
+        final AccountController accountController = mActivity.getAccountController();
+        mAccountObserver = new AccountObserver() {
+            @Override
+            public void onChanged(Account newAccount) {
+                setSelectedAccount(newAccount);
+            }
+        };
+        if (accountController != null) {
+            // Current account and its observer.
+            mCurrentAccount = mAccountObserver.initialize(accountController);
+            // List of all accounts and its observer.
+            mAllAccountObserver = new AllAccountObserver(){
+                @Override
+                public void onChanged(Account[] allAccounts) {
+                    mAllAccounts = allAccounts;
+                }
+            };
+            mAllAccounts = mAllAccountObserver.initialize(accountController);
+            mAccountChanger = accountController;
         }
 
-        mListener = mActivity.getFolderListSelectionListener();
+        mFolderChanger = mActivity.getFolderListSelectionListener();
         if (mActivity.isFinishing()) {
             // Activity is finishing, just bail.
             return;
@@ -197,7 +222,12 @@
             mCursorAdapter = new HierarchicalFolderListAdapter(null, mParentFolder);
             selectedFolder = mActivity.getHierarchyFolder();
         } else {
-            mCursorAdapter = new FolderListAdapter(R.layout.folder_item, mIsSectioned);
+            // Initiate FLA with accounts and folders collapsed in the list
+            // The second param is for whether folders should be collapsed
+            // The third param is for whether accounts should be collapsed
+            mCursorAdapter = new FolderListAdapter(mIsSectioned,
+                    !mIsTabletUI && ARE_ITEMS_COLLAPSED,
+                    !mIsTabletUI && ARE_ITEMS_COLLAPSED);
             selectedFolder = controller == null ? null : controller.getFolder();
         }
         // Is the selected folder fresher than the one we have restored from a bundle?
@@ -216,6 +246,7 @@
         mFolderListUri = Uri.parse(args.getString(ARG_FOLDER_URI));
         mParentFolder = (Folder) args.getParcelable(ARG_PARENT_FOLDER);
         mIsSectioned = args.getBoolean(ARG_IS_SECTIONED);
+        mIsTabletUI = args.getBoolean(ARG_IS_TABLET_UI);
         mExcludedFolderTypes = args.getIntegerArrayList(ARG_EXCLUDED_FOLDER_TYPES);
         final View rootView = inflater.inflate(R.layout.folder_list, null);
         mListView = (ListView) rootView.findViewById(android.R.id.list);
@@ -272,31 +303,54 @@
         // Clear the adapter.
         setListAdapter(null);
         if (mFolderObserver != null) {
-            FolderController controller = mActivity.getFolderController();
-            if (controller != null) {
-                controller.unregisterFolderObserver(mFolderObserver);
-                mFolderObserver = null;
-            }
+            mFolderObserver.unregisterAndDestroy();
+            mFolderObserver = null;
+        }
+        if (mAccountObserver != null) {
+            mAccountObserver.unregisterAndDestroy();
+            mAccountObserver = null;
+        }
+        if (mAllAccountObserver != null) {
+            mAllAccountObserver.unregisterAndDestroy();
+            mAllAccountObserver = null;
         }
         super.onDestroyView();
     }
 
     @Override
     public void onListItemClick(ListView l, View v, int position, long id) {
-        viewFolder(position);
+        viewFolderOrChangeAccount(position);
     }
 
     /**
      * Display the conversation list from the folder at the position given.
-     * @param position
+     * @param position a zero indexed position into the list.
      */
-    private void viewFolder(int position) {
+    private void viewFolderOrChangeAccount(int position) {
         final Object item = getListAdapter().getItem(position);
         final Folder folder;
-        if (item instanceof FolderListAdapter.Item) {
-            final FolderListAdapter.Item folderItem = (FolderListAdapter.Item) item;
-            folder = mCursorAdapter.getFullFolder(folderItem);
-            mSelectedFolderType = folderItem.mFolderType;
+        if (item instanceof DrawerItem) {
+            final DrawerItem folderItem = (DrawerItem) item;
+            // Could be a folder, account, or expand block.
+            final int itemType = mCursorAdapter.getItemType(folderItem);
+            if (itemType == DrawerItem.VIEW_ACCOUNT) {
+                // Account, so switch.
+                folder = null;
+                final Account account = mCursorAdapter.getFullAccount(folderItem);
+                mAccountChanger.changeAccount(account);
+            } else if (itemType == DrawerItem.VIEW_FOLDER) {
+                // Folder type, so change folders only.
+                folder = mCursorAdapter.getFullFolder(folderItem);
+                mSelectedFolderType = folderItem.mFolderType;
+            } else {
+                // Block for expanding/contracting labels/accounts
+                folder = null;
+                if(!folderItem.mIsExpandForAccount) {
+                    mCursorAdapter.toggleShowLessFolders();
+                } else {
+                    mCursorAdapter.toggleShowLessAccounts();
+                }
+            }
         } else if (item instanceof Folder) {
             folder = (Folder) item;
         } else {
@@ -309,10 +363,7 @@
             // update its parent!
             folder.parent = folder.equals(mParentFolder) ? null : mParentFolder;
             // Go to the conversation list for this folder.
-            mListener.onFolderSelected(folder);
-        } else {
-            LogUtils.d(LOG_TAG, "FolderListFragment unable to get a full fledged folder" +
-                    " to hand to the listener for position %d", position);
+            mFolderChanger.onFolderSelected(folder);
         }
     }
 
@@ -360,8 +411,21 @@
     private interface FolderListFragmentCursorAdapter extends ListAdapter {
         /** Update the folder list cursor with the cursor given here. */
         void setCursor(Cursor cursor);
-        /** Get the cursor associated with this adapter **/
-        Folder getFullFolder(FolderListAdapter.Item item);
+        /** Toggles showing more accounts or less accounts. */
+        boolean toggleShowLessAccounts();
+        /** Toggles showing more folders or less. */
+        boolean toggleShowLessFolders();
+        /**
+         * Given an item, find the type of the item, which is {@link
+         * DrawerItem#VIEW_FOLDER}, {@link DrawerItem#VIEW_ACCOUNT} or
+         * {@link DrawerItem#VIEW_MORE}
+         * @return the type of the item.
+         */
+        int getItemType(DrawerItem item);
+        /** Get the folder associated with this item. **/
+        Folder getFullFolder(DrawerItem item);
+        /** Get the account associated with this item. **/
+        Account getFullAccount(DrawerItem item);
         /** Remove all observers and destroy the object. */
         void destroy();
         /** Notifies the adapter that the data has changed. */
@@ -380,131 +444,30 @@
             }
         };
 
+        /** After given number of accounts, show "more" until expanded. */
+        private static final int MAX_ACCOUNTS = 2;
+        /** After the given number of labels, show "more" until expanded. */
+        private static final int MAX_FOLDERS = 7;
+
         private final RecentFolderList mRecentFolders;
         /** True if the list is sectioned, false otherwise */
         private final boolean mIsSectioned;
-        private final LayoutInflater mInflater;
         /** All the items */
-        private final List<Item> mItemList = new ArrayList<Item>();
+        private final List<DrawerItem> mItemList = new ArrayList<DrawerItem>();
         /** Cursor into the folder list. This might be null. */
         private Cursor mCursor = null;
-
-        /** A union of either a folder or a resource string */
-        private class Item {
-            public int mPosition;
-            public final Folder mFolder;
-            public final int mResource;
-            /** Either {@link #VIEW_FOLDER} or {@link #VIEW_HEADER} */
-            public final int mType;
-            /** A normal folder, also a child, if a parent is specified. */
-            private static final int VIEW_FOLDER = 0;
-            /** A text-label which serves as a header in sectioned lists. */
-            private static final int VIEW_HEADER = 1;
-
-            /**
-             * Either {@link #FOLDER_SYSTEM}, {@link #FOLDER_RECENT} or {@link #FOLDER_USER} when
-             * {@link #mType} is {@link #VIEW_FOLDER}, and {@link #NOT_A_FOLDER} otherwise.
-             */
-            public final int mFolderType;
-            private static final int NOT_A_FOLDER = 0;
-            private static final int FOLDER_SYSTEM = 1;
-            private static final int FOLDER_RECENT = 2;
-            private static final int FOLDER_USER = 3;
-
-            /**
-             * Create a folder item with the given type.
-             * @param folder
-             * @param folderType one of {@link #FOLDER_SYSTEM}, {@link #FOLDER_RECENT} or
-             * {@link #FOLDER_USER}
-             */
-            private Item(Folder folder, int folderType, int cursorPosition) {
-                mFolder = folder;
-                mResource = -1;
-                mType = VIEW_FOLDER;
-                mFolderType = folderType;
-                mPosition = cursorPosition;
-            }
-            /**
-             * Create a header item with a string resource.
-             * @param resource the string resource: R.string.all_folders_heading
-             */
-            private Item(int resource) {
-                mFolder = null;
-                mResource = resource;
-                mType = VIEW_HEADER;
-                mFolderType = NOT_A_FOLDER;
-            }
-
-            private final View getView(int position, View convertView, ViewGroup parent) {
-                if (mType == VIEW_FOLDER) {
-                    return getFolderView(position, convertView, parent);
-                } else {
-                    return getHeaderView(position, convertView, parent);
-                }
-            }
-
-            /**
-             * Returns a text divider between sections.
-             * @param convertView
-             * @param parent
-             * @return a text header at the given position.
-             */
-            private final View getHeaderView(int position, View convertView, ViewGroup parent) {
-                final TextView headerView;
-                if (convertView != null) {
-                    headerView = (TextView) convertView;
-                } else {
-                    headerView = (TextView) mInflater.inflate(
-                            R.layout.folder_list_header, parent, false);
-                }
-                headerView.setText(mResource);
-                return headerView;
-            }
-
-            /**
-             * Return a folder: either a parent folder or a normal (child or flat)
-             * folder.
-             * @param position
-             * @param convertView
-             * @param parent
-             * @return a view showing a folder at the given position.
-             */
-            private final View getFolderView(int position, View convertView, ViewGroup parent) {
-                final FolderItemView folderItemView;
-                if (convertView != null) {
-                    folderItemView = (FolderItemView) convertView;
-                } else {
-                    folderItemView =
-                            (FolderItemView) mInflater.inflate(R.layout.folder_item, null, false);
-                }
-                folderItemView.bind(mFolder, mActivity);
-                if (mListView != null) {
-                    final boolean isSelected = (mFolderType == mSelectedFolderType)
-                            && mFolder.uri.equals(mSelectedFolderUri);
-                    mListView.setItemChecked(position, isSelected);
-                    // If this is the current folder, also check to verify that the unread count
-                    // matches what the action bar shows.
-                    if (isSelected && (mCurrentFolderForUnreadCheck != null)
-                            && mFolder.unreadCount != mCurrentFolderForUnreadCheck.unreadCount) {
-                        folderItemView.overrideUnreadCount(
-                                mCurrentFolderForUnreadCheck.unreadCount);
-                    }
-                }
-                Folder.setFolderBlockColor(mFolder, folderItemView.findViewById(R.id.color_block));
-                Folder.setIcon(mFolder, (ImageView) folderItemView.findViewById(R.id.folder_icon));
-                return folderItemView;
-            }
-        }
+        /** Watcher for tracking and receiving unread counts for mail */
+        private FolderWatcher mFolderWatcher = null;
+        private boolean mShowLessFolders;
+        private boolean mShowLessAccounts;
 
         /**
          * Creates a {@link FolderListAdapter}.This is a flat folder list of all the folders for the
          * given account.
-         * @param layout
          * @param isSectioned TODO(viki):
          */
-        public FolderListAdapter(int layout, boolean isSectioned) {
+        public FolderListAdapter(boolean isSectioned, boolean showLess, boolean showLessAccounts) {
             super();
-            mInflater = LayoutInflater.from(mActivity.getActivityContext());
             mIsSectioned = isSectioned;
             final RecentFolderController controller = mActivity.getRecentFolderController();
             if (controller != null && mIsSectioned) {
@@ -512,22 +475,48 @@
             } else {
                 mRecentFolders = null;
             }
+            mFolderWatcher = new FolderWatcher(mActivity, this);
+            mShowLessFolders = showLess;
+            mShowLessAccounts = showLessAccounts;
+            for (int i=0; i < mAllAccounts.length; i++) {
+                final Uri uri = mAllAccounts[i].settings.defaultInbox;
+                mFolderWatcher.startWatching(uri);
+            }
         }
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
-            return ((Item) getItem(position)).getView(position, convertView, parent);
+            final DrawerItem item = (DrawerItem) getItem(position);
+            final View view = item.getView(position, convertView, parent);
+            final int type = item.mType;
+            if (mListView!= null) {
+                final boolean isSelected =
+                        item.isHighlighted(mCurrentFolderForUnreadCheck, mSelectedFolderType);
+                if (type == DrawerItem.VIEW_FOLDER) {
+                    mListView.setItemChecked(position, isSelected);
+                }
+                // If this is the current folder, also check to verify that the unread count
+                // matches what the action bar shows.
+                if (type == DrawerItem.VIEW_FOLDER
+                        && isSelected
+                        && (mCurrentFolderForUnreadCheck != null)
+                        && item.mFolder.unreadCount != mCurrentFolderForUnreadCheck.unreadCount) {
+                    ((FolderItemView) view).overrideUnreadCount(
+                            mCurrentFolderForUnreadCheck.unreadCount);
+                }
+            }
+            return view;
         }
 
         @Override
         public int getViewTypeCount() {
-            // Headers and folders
-            return 2;
+            // Accounts, headers and folders
+            return DrawerItem.getViewTypes();
         }
 
         @Override
         public int getItemViewType(int position) {
-            return ((Item) getItem(position)).mType;
+            return ((DrawerItem) getItem(position)).mType;
         }
 
         @Override
@@ -537,22 +526,27 @@
 
         @Override
         public boolean isEnabled(int position) {
-            // We disallow taps on headers
-            return ((Item) getItem(position)).mType != Item.VIEW_HEADER;
+            final DrawerItem item = (DrawerItem) getItem(position);
+            return item.isItemEnabled(getCurrentAccountUri());
+
+        }
+
+        private Uri getCurrentAccountUri() {
+            return mCurrentAccount == null ? Uri.EMPTY : mCurrentAccount.uri;
         }
 
         @Override
         public boolean areAllItemsEnabled() {
-            // The headers are not enabled.
+            // The headers and current accounts are not enabled.
             return false;
         }
 
         /**
          * Returns all the recent folders from the list given here. Safe to call with a null list.
-         * @param recentList
+         * @param recentList a list of all recently accessed folders.
          * @return a valid list of folders, which are all recent folders.
          */
-        private final List<Folder> getRecentFolders(RecentFolderList recentList) {
+        private List<Folder> getRecentFolders(RecentFolderList recentList) {
             final List<Folder> folderList = new ArrayList<Folder>();
             if (recentList == null) {
                 return folderList;
@@ -567,21 +561,84 @@
         }
 
         /**
-         * Recalculates the system, recent and user label lists. Notifies that the data has changed.
-         * This method modifies all the three lists on every single invocation.
+         * Toggle boolean for what folders are shown and which ones are
+         * hidden. Redraws list after toggling to show changes.
+         * @return true if folders are hidden, false if all are shown
+         */
+        @Override
+        public boolean toggleShowLessFolders() {
+            mShowLessFolders = !mShowLessFolders;
+            recalculateList();
+            return mShowLessFolders;
+        }
+
+        /**
+         * Toggle boolean for what accounts are shown and which ones are
+         * hidden. Redraws list after toggling to show changes.
+         * @return true if accounts are hidden, false if all are shown
+         */
+        @Override
+        public boolean toggleShowLessAccounts() {
+            mShowLessAccounts = !mShowLessAccounts;
+            recalculateList();
+            return mShowLessAccounts;
+        }
+
+        /**
+         * Responsible for verifying mCursor, adding collapsed view items
+         * when necessary, and notifying the data set has changed.
          */
         private void recalculateList() {
             if (mCursor == null || mCursor.isClosed() || mCursor.getCount() <= 0
                     || !mCursor.moveToFirst()) {
                 return;
             }
+            recalculateListFolders();
+            if(mShowLessFolders) {
+                mItemList.add(new DrawerItem(mActivity, R.string.folder_list_more, false));
+            }
+            // Ask the list to invalidate its views.
+            notifyDataSetChanged();
+        }
+
+        /**
+         * Recalculates the system, recent and user label lists.
+         * This method modifies all the three lists on every single invocation.
+         */
+        private void recalculateListFolders() {
             mItemList.clear();
+            if (mAllAccounts != null) {
+                // Add the accounts at the top.
+                // TODO(shahrk): The logic here is messy and will be changed
+                //               to properly add/reflect on LRU/MRU account
+                //               changes similar to RecentFoldersList
+                if (mShowLessAccounts && mAllAccounts.length > MAX_ACCOUNTS) {
+                    mItemList.add(new DrawerItem(
+                            mActivity, R.string.folder_list_show_all_accounts, true));
+                    final int unreadCount =
+                            getFolderUnreadCount(mCurrentAccount.settings.defaultInbox);
+                    mItemList.add(new DrawerItem(mActivity, mCurrentAccount, unreadCount));
+                } else {
+                    Uri currentAccountUri = getCurrentAccountUri();
+                    for (final Account c : mAllAccounts) {
+                        if (!currentAccountUri.equals(c.uri)) {
+                            final int otherAccountUnreadCount =
+                                    getFolderUnreadCount(c.settings.defaultInbox);
+                            mItemList.add(new DrawerItem(mActivity, c, otherAccountUnreadCount));
+                        }
+                    }
+                    final int accountUnreadCount =
+                            getFolderUnreadCount(mCurrentAccount.settings.defaultInbox);
+                    mItemList.add(new DrawerItem(mActivity, mCurrentAccount, accountUnreadCount));
+                }
+            }
             if (!mIsSectioned) {
                 // Adapter for a flat list. Everything is a FOLDER_USER, and there are no headers.
                 do {
                     final Folder f = Folder.getDeficientDisplayOnlyFolder(mCursor);
                     if (mExcludedFolderTypes == null || !mExcludedFolderTypes.contains(f.type)) {
-                        mItemList.add(new Item(f, Item.FOLDER_USER, mCursor.getPosition()));
+                        mItemList.add(new DrawerItem(mActivity, f, DrawerItem.FOLDER_USER,
+                                mCursor.getPosition()));
                     }
                 } while (mCursor.moveToNext());
                 // Ask the list to invalidate its views.
@@ -589,16 +646,25 @@
                 return;
             }
 
+            // Tracks how many folders have been added through the rest of the function
+            int folderCount = 0;
             // Otherwise, this is an adapter for a sectioned list.
             // First add all the system folders.
-            final List<Item> userFolderList = new ArrayList<Item>();
+            final List<DrawerItem> userFolderList = new ArrayList<DrawerItem>();
             do {
                 final Folder f = Folder.getDeficientDisplayOnlyFolder(mCursor);
                 if (mExcludedFolderTypes == null || !mExcludedFolderTypes.contains(f.type)) {
                     if (f.isProviderFolder()) {
-                        mItemList.add(new Item(f, Item.FOLDER_SYSTEM, mCursor.getPosition()));
+                        mItemList.add(new DrawerItem(mActivity, f, DrawerItem.FOLDER_SYSTEM,
+                                mCursor.getPosition()));
+                        // Check if show less is enabled and we've passed max folders
+                        folderCount++;
+                        if(mShowLessFolders && folderCount >= MAX_FOLDERS) {
+                            return;
+                        }
                     } else {
-                        userFolderList.add(new Item(f, Item.FOLDER_USER, mCursor.getPosition()));
+                        userFolderList.add(new DrawerItem(
+                                mActivity, f, DrawerItem.FOLDER_USER, mCursor.getPosition()));
                     }
                 }
             } while (mCursor.moveToNext());
@@ -616,20 +682,33 @@
             }
 
             if (recentFolderList.size() > 0) {
-                mItemList.add(new Item(R.string.recent_folders_heading));
+                mItemList.add(new DrawerItem(mActivity, R.string.recent_folders_heading));
                 for (Folder f : recentFolderList) {
-                    mItemList.add(new Item(f, Item.FOLDER_RECENT, -1));
+                    mItemList.add(new DrawerItem(mActivity, f, DrawerItem.FOLDER_RECENT, -1));
+                    // Check if show less is enabled and we've passed max folders
+                    folderCount++;
+                    if(mShowLessFolders && folderCount >= MAX_FOLDERS) {
+                        return;
+                    }
                 }
             }
             // If there are user folders, add them and a header.
             if (userFolderList.size() > 0) {
-                mItemList.add(new Item(R.string.all_folders_heading));
-                for (final Item i : userFolderList) {
+                mItemList.add(new DrawerItem(mActivity, R.string.all_folders_heading));
+                for (final DrawerItem i : userFolderList) {
                     mItemList.add(i);
+                    // Check if show less is enabled and we've passed max folders
+                    folderCount++;
+                    if(mShowLessFolders && folderCount >= MAX_FOLDERS) {
+                        return;
+                    }
                 }
             }
-            // Ask the list to invalidate its views.
-            notifyDataSetChanged();
+        }
+
+        private int getFolderUnreadCount(Uri folderUri) {
+            final Folder folder = mFolderWatcher.get(folderUri);
+            return folder != null ? folder.unreadCount : 0;
         }
 
         @Override
@@ -654,8 +733,13 @@
         }
 
         @Override
-        public Folder getFullFolder(Item folderItem) {
-            if (folderItem.mFolderType == Item.FOLDER_RECENT) {
+        public int getItemType(DrawerItem item) {
+            return item.mType;
+        }
+
+        @Override
+        public Folder getFullFolder(DrawerItem folderItem) {
+            if (folderItem.mFolderType == DrawerItem.FOLDER_RECENT) {
                 return folderItem.mFolder;
             } else {
                 int pos = folderItem.mPosition;
@@ -671,6 +755,11 @@
                 }
             }
         }
+
+        @Override
+        public Account getFullAccount(DrawerItem item) {
+            return item.mAccount;
+        }
     }
 
     private class HierarchicalFolderListAdapter extends ArrayAdapter<Folder>
@@ -699,14 +788,14 @@
 
         @Override
         public int getItemViewType(int position) {
-            Folder f = getItem(position);
+            final Folder f = getItem(position);
             return f.uri.equals(mParentUri) ? PARENT : CHILD;
         }
 
         @Override
         public View getView(int position, View convertView, ViewGroup parent) {
-            FolderItemView folderItemView;
-            Folder folder = getItem(position);
+            final FolderItemView folderItemView;
+            final Folder folder = getItem(position);
             boolean isParent = folder.uri.equals(mParentUri);
             if (convertView != null) {
                 folderItemView = (FolderItemView) convertView;
@@ -754,7 +843,13 @@
         }
 
         @Override
-        public Folder getFullFolder(FolderListAdapter.Item folderItem) {
+        public int getItemType(DrawerItem item) {
+            // Always returns folders for now.
+            return DrawerItem.VIEW_FOLDER;
+        }
+
+        @Override
+        public Folder getFullFolder(DrawerItem folderItem) {
             int pos = folderItem.mPosition;
             if (mCursor == null || mCursor.isClosed()) {
                 // See if we have a cursor hanging out we can use
@@ -768,6 +863,21 @@
                 return null;
             }
         }
+
+        @Override
+        public Account getFullAccount(DrawerItem item) {
+            return null;
+        }
+
+        @Override
+        public boolean toggleShowLessFolders() {
+            return false;
+        }
+
+        @Override
+        public boolean toggleShowLessAccounts() {
+            return false;
+        }
     }
 
     /**
@@ -782,7 +892,7 @@
         }
         // If the current folder changed, we don't have a selected folder type anymore.
         if (!folder.uri.equals(mSelectedFolderUri)) {
-            mSelectedFolderType = FolderListAdapter.Item.NOT_A_FOLDER;
+            mSelectedFolderType = DrawerItem.INERT_HEADER;
         }
         mCurrentFolderForUnreadCheck = folder;
         mSelectedFolderUri = folder.uri;
@@ -794,15 +904,23 @@
 
     /**
      * Sets the selected folder type safely.
-     * @param folder
+     * @param folder folder to set to.
      */
     private void setSelectedFolderType(Folder folder) {
         // If it is set already, assume it is correct.
-        if (mSelectedFolderType != FolderListAdapter.Item.NOT_A_FOLDER) {
+        if (mSelectedFolderType != DrawerItem.INERT_HEADER) {
             return;
         }
-        mSelectedFolderType = folder.isProviderFolder() ? FolderListAdapter.Item.FOLDER_SYSTEM
-                : FolderListAdapter.Item.FOLDER_USER;
+        mSelectedFolderType = folder.isProviderFolder() ? DrawerItem.FOLDER_SYSTEM
+                : DrawerItem.FOLDER_USER;
+    }
+
+    /**
+     * Sets the current account to the one provided here.
+     * @param account the current account to set to.
+     */
+    private void setSelectedAccount(Account account){
+        mCurrentAccount = account;
     }
 
     public interface FolderListSelectionListener {
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index c336ff3..3bee9b0 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -110,7 +110,7 @@
     private void createFolderListFragment(Folder parent, Uri uri) {
         final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
         final Fragment fragment = FolderListFragment.newInstance(parent, uri, false,
-                getExcludedFolderTypes());
+                getExcludedFolderTypes(), true);
         fragmentTransaction.replace(R.id.content_pane, fragment);
         fragmentTransaction.commitAllowingStateLoss();
     }
@@ -371,4 +371,10 @@
         // Unsupported
         return true;
     }
+
+    @Override
+    public ConversationListHelper getConversationListHelper() {
+        // Unsupported
+        return null;
+    }
 }
diff --git a/src/com/android/mail/ui/FolderSelectorAdapter.java b/src/com/android/mail/ui/FolderSelectorAdapter.java
index c9f7718..d5d85af 100644
--- a/src/com/android/mail/ui/FolderSelectorAdapter.java
+++ b/src/com/android/mail/ui/FolderSelectorAdapter.java
@@ -211,9 +211,9 @@
         if (view == null) {
             view = mInflater.inflate(mLayout, parent, false);
         }
-        FolderRow row = (FolderRow) getItem(position);
-        Folder folder = row.getFolder();
-        String folderDisplay = !TextUtils.isEmpty(folder.hierarchicalDesc) ?
+        final FolderRow row = (FolderRow) getItem(position);
+        final Folder folder = row.getFolder();
+        final String folderDisplay = !TextUtils.isEmpty(folder.hierarchicalDesc) ?
                 folder.hierarchicalDesc : folder.name;
         checkBox = (CompoundButton) view.findViewById(R.id.checkbox);
         display = (TextView) view.findViewById(R.id.folder_name);
diff --git a/src/com/android/mail/ui/HtmlConversationTemplates.java b/src/com/android/mail/ui/HtmlConversationTemplates.java
index 5eeeb3e..92340b3 100644
--- a/src/com/android/mail/ui/HtmlConversationTemplates.java
+++ b/src/com/android/mail/ui/HtmlConversationTemplates.java
@@ -182,7 +182,7 @@
 
     public String endConversation(String docBaseUri, String conversationBaseUri, int viewWidth,
             int viewportWidth, boolean enableContentReadySignal, boolean normalizeMessageWidths,
-            boolean enableMungeTables) {
+            boolean enableMungeTables, boolean enableMungeImages) {
         if (!mInProgress) {
             throw new IllegalStateException("must call startConversation first");
         }
@@ -192,7 +192,7 @@
         append(sConversationLower, contentReadyClass, mContext.getString(R.string.hide_elided),
                 mContext.getString(R.string.show_elided), docBaseUri, conversationBaseUri,
                 viewWidth, viewportWidth, enableContentReadySignal, normalizeMessageWidths,
-                enableMungeTables);
+                enableMungeTables, enableMungeImages);
 
         mInProgress = false;
 
diff --git a/src/com/android/mail/ui/MailActionBarView.java b/src/com/android/mail/ui/MailActionBarView.java
index 9202569..9e94d33 100644
--- a/src/com/android/mail/ui/MailActionBarView.java
+++ b/src/com/android/mail/ui/MailActionBarView.java
@@ -17,6 +17,23 @@
 
 package com.android.mail.ui;
 
+import com.android.mail.ConversationListContext;
+import com.android.mail.R;
+import com.android.mail.browse.SnippetTextView;
+import com.android.mail.providers.Account;
+import com.android.mail.providers.AccountObserver;
+import com.android.mail.providers.AllAccountObserver;
+import com.android.mail.providers.Conversation;
+import com.android.mail.providers.Folder;
+import com.android.mail.providers.FolderObserver;
+import com.android.mail.providers.SearchRecentSuggestionsProvider;
+import com.android.mail.providers.UIProvider;
+import com.android.mail.providers.UIProvider.AccountCapabilities;
+import com.android.mail.providers.UIProvider.FolderCapabilities;
+import com.android.mail.utils.LogTag;
+import com.android.mail.utils.LogUtils;
+import com.android.mail.utils.Utils;
+
 import android.app.ActionBar;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -24,7 +41,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.Cursor;
-import android.database.DataSetObserver;
 import android.os.Bundle;
 import android.os.Handler;
 import android.text.SpannableString;
@@ -40,22 +56,6 @@
 import android.widget.SearchView.OnQueryTextListener;
 import android.widget.SearchView.OnSuggestionListener;
 
-import com.android.mail.AccountSpinnerAdapter;
-import com.android.mail.ConversationListContext;
-import com.android.mail.R;
-import com.android.mail.browse.SnippetTextView;
-import com.android.mail.providers.Account;
-import com.android.mail.providers.AccountObserver;
-import com.android.mail.providers.Conversation;
-import com.android.mail.providers.Folder;
-import com.android.mail.providers.SearchRecentSuggestionsProvider;
-import com.android.mail.providers.UIProvider;
-import com.android.mail.providers.UIProvider.AccountCapabilities;
-import com.android.mail.providers.UIProvider.FolderCapabilities;
-import com.android.mail.utils.LogTag;
-import com.android.mail.utils.LogUtils;
-import com.android.mail.utils.Utils;
-
 /**
  * View to manage the various states of the Mail Action Bar.
  * <p>
@@ -78,8 +78,6 @@
     private int mMode = ViewMode.UNKNOWN;
 
     private MenuItem mSearch;
-    private AccountSpinnerAdapter mSpinnerAdapter;
-    private MailSpinner mSpinner;
     /**
      * The account currently being shown
      */
@@ -96,12 +94,12 @@
     private MenuItem mRefreshItem;
     private MenuItem mFolderSettingsItem;
     private View mRefreshActionView;
+    /** True if the current device is a tablet, false otherwise. */
+    private boolean mIsOnTablet;
     private boolean mRefreshInProgress;
     private Conversation mCurrentConversation;
-    /**
-     * True if we are running on tablet.
-     */
-    private final boolean mIsOnTablet;
+    private AllAccountObserver mAllAccountObserver;
+    private boolean mHaveMultipleAccounts = false;
 
     public static final String LOG_TAG = LogTag.getLogTag();
 
@@ -113,13 +111,12 @@
         }
     };
     private final boolean mShowConversationSubject;
-    private DataSetObserver mFolderObserver;
+    private FolderObserver mFolderObserver;
 
     private final AccountObserver mAccountObserver = new AccountObserver() {
         @Override
         public void onChanged(Account newAccount) {
             updateAccount(newAccount);
-            mSpinner.setAccount(mAccount);
         }
     };
 
@@ -165,9 +162,6 @@
         return reports;
     }
 
-    /** True if the application has more than one account. */
-    private boolean mHasManyAccounts;
-
     // Created via view inflation.
     @SuppressWarnings("unused")
     public MailActionBarView(Context context) {
@@ -185,18 +179,9 @@
         mIsOnTablet = Utils.useTabletUI(r);
     }
 
-    // update the pager title strip as the Folder's conversation count changes
-    private class FolderObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            onFolderUpdated(mController.getFolder());
-        }
-    }
-
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-
         mSubjectView = (SnippetTextView) findViewById(R.id.conversation_subject);
     }
 
@@ -281,26 +266,32 @@
         mActionBar = actionBar;
         mController = callback;
         mActivity = activity;
-        mFolderObserver = new FolderObserver();
-        mController.registerFolderObserver(mFolderObserver);
-        // We don't want to include the "Show all folders" menu item on tablet devices
-        final Context context = getContext();
-        final boolean showAllFolders = !Utils.useTabletUI(context.getResources());
-        mSpinnerAdapter = new AccountSpinnerAdapter(activity, context, showAllFolders);
-        mSpinner = (MailSpinner) findViewById(R.id.account_spinner);
-        mSpinner.setAdapter(mSpinnerAdapter);
-        mSpinner.setController(mController);
+        mFolderObserver = new FolderObserver() {
+            @Override
+            public void onChanged(Folder newFolder) {
+                onFolderUpdated(newFolder);
+            }
+        };
+        mFolderObserver.initialize(mController);
+        mAllAccountObserver = new AllAccountObserver() {
+            @Override
+            public void onChanged(Account[] allAccounts) {
+                mHaveMultipleAccounts = (allAccounts.length > 1);
+            }
+        };
+        mAllAccountObserver.initialize(mController);
         updateAccount(mAccountObserver.initialize(activity.getAccountController()));
     }
 
     private void updateAccount(Account account) {
         mAccount = account;
         if (mAccount != null) {
-            ContentResolver resolver = mActivity.getActivityContext().getContentResolver();
-            Bundle bundle = new Bundle(1);
+            final ContentResolver resolver = mActivity.getActivityContext().getContentResolver();
+            final Bundle bundle = new Bundle(1);
             bundle.putParcelable(UIProvider.SetCurrentAccountColumns.ACCOUNT, account);
             resolver.call(mAccount.uri, UIProvider.AccountCallMethods.SET_CURRENT_ACCOUNT,
                     mAccount.uri.toString(), bundle);
+            setFolderAndAccount();
         }
     }
 
@@ -312,72 +303,34 @@
     }
 
     /**
-     * Sets the array of accounts to the value provided here.
-     * @param accounts array of all accounts on the device.
-     */
-    public void setAccounts(Account[] accounts) {
-        mSpinnerAdapter.setAccountArray(accounts);
-        mHasManyAccounts = accounts.length > 1;
-        enableDisableSpinnner();
-    }
-
-    /**
-     * Changes the spinner state according to the following logic. On phone we always show recent
-     * labels: pre-populating if necessary. So on phone we always want to enable the spinner.
-     * On tablet, we enable the spinner when the Folder list is NOT visible: In conversation view,
-     * and search conversation view.
-     */
-    private void enableDisableSpinnner() {
-        // Spinner is always shown on phone, and it is enabled by default, so don't mess with it.
-        // By default the drawable is set in the XML layout, and the view is enabled.
-        if (!mIsOnTablet) {
-            return;
-        }
-        // We do not populate default recent folders on tablet, so we need to check that in the
-        // conversation mode we have some recent folders. If we don't have any, then we should
-        // disable the spinner.
-        final boolean hasRecentsInConvView = ViewMode.isConversationMode(mMode)
-                && mSpinnerAdapter.hasRecentFolders();
-        // More than one account, OR has recent folders in conversation view.
-        final boolean enabled = mHasManyAccounts || hasRecentsInConvView;
-        mSpinner.changeEnabledState(enabled);
-    }
-
-    /**
      * Called by the owner of the ActionBar to set the
      * folder that is currently being displayed.
      */
     public void setFolder(Folder folder) {
         setRefreshInProgress(false);
         mFolder = folder;
-        mSpinner.setFolder(folder);
+        setFolderAndAccount();
         mActivity.invalidateOptionsMenu();
     }
 
     public void onDestroy() {
         if (mFolderObserver != null) {
-            mController.unregisterFolderObserver(mFolderObserver);
+            mFolderObserver.unregisterAndDestroy();
             mFolderObserver = null;
         }
-        mSpinnerAdapter.destroy();
+        if (mAllAccountObserver != null) {
+            mAllAccountObserver.unregisterAndDestroy();
+            mAllAccountObserver = null;
+        }
         mAccountObserver.unregisterAndDestroy();
     }
 
     @Override
     public void onViewModeChanged(int newMode) {
         mMode = newMode;
-        // Always update the options menu and redraw. This will read the new mode and redraw
-        // the options menu.
-        enableDisableSpinnner();
         mActivity.invalidateOptionsMenu();
         // Check if we are either on a phone, or in Conversation mode on tablet. For these, the
         // recent folders is enabled.
-        if (!mIsOnTablet || mMode == ViewMode.CONVERSATION) {
-            mSpinnerAdapter.enableRecentFolders();
-        } else {
-            mSpinnerAdapter.disableRecentFolders();
-        }
-
         switch (mMode) {
             case ViewMode.UNKNOWN:
                 closeSearchField();
@@ -480,9 +433,9 @@
      * Put the ActionBar in List navigation mode. This starts the spinner up if it is missing.
      */
     private void showNavList() {
-        setTitleModeFlags(ActionBar.DISPLAY_SHOW_CUSTOM);
-        mSpinner.setVisibility(View.VISIBLE);
+        setTitleModeFlags(ActionBar.DISPLAY_SHOW_TITLE);
         mSubjectView.setVisibility(View.GONE);
+        setFolderAndAccount();
     }
 
     /**
@@ -492,24 +445,23 @@
      */
     protected void setSnippetMode() {
         setTitleModeFlags(ActionBar.DISPLAY_SHOW_CUSTOM);
-        mSpinner.setVisibility(View.GONE);
         mSubjectView.setVisibility(View.VISIBLE);
-
         mSubjectView.addOnLayoutChangeListener(mSnippetLayoutListener);
     }
 
     private void setFoldersMode() {
         setTitleModeFlags(ActionBar.DISPLAY_SHOW_TITLE);
         mActionBar.setTitle(R.string.folders);
-        mActionBar.setSubtitle(mAccount.name);
+        if (mHaveMultipleAccounts) {
+            mActionBar.setSubtitle(mAccount.name);
+        }
     }
 
     /**
      * Set the actionbar mode to empty: no title, no custom content.
      */
     protected void setEmptyMode() {
-        setTitleModeFlags(ActionBar.DISPLAY_SHOW_CUSTOM);
-        mSpinner.setVisibility(View.GONE);
+        setTitleModeFlags(ActionBar.DISPLAY_SHOW_TITLE);
         mSubjectView.setVisibility(View.GONE);
     }
 
@@ -618,10 +570,30 @@
     }
 
     /**
+     * Uses the current state to update the current folder {@link #mFolder} and the current
+     * account {@link #mAccount} shown in the actionbar.
+     */
+    private void setFolderAndAccount() {
+        // Check if we should be changing the actionbar at all, and back off if not.
+        final boolean isShowingFolderAndAccount =
+                (mActionBar != null && (mIsOnTablet || ViewMode.isListMode(mMode)));
+        if (!isShowingFolderAndAccount) {
+            return;
+        }
+        if (mFolder != null) {
+            mActionBar.setTitle(mFolder.name);
+        }
+        if (mAccount != null && mHaveMultipleAccounts) {
+            mActionBar.setSubtitle(mAccount.name);
+        }
+        // TODO(viki): Show unread count.
+    }
+
+    /**
      * Notify that the folder has changed.
      */
     public void onFolderUpdated(Folder folder) {
-        mSpinner.onFolderUpdated(folder);
+        setFolderAndAccount();
         if (folder.isSyncInProgress()) {
             onRefreshStarted();
         } else {
@@ -660,7 +632,6 @@
     private void setTitleModeFlags(int enabledFlags) {
         final int mask = ActionBar.DISPLAY_SHOW_TITLE
                 | ActionBar.DISPLAY_SHOW_CUSTOM | DISPLAY_TITLE_MULTIPLE_LINES;
-
         mActionBar.setDisplayOptions(enabledFlags, mask);
     }
 
@@ -736,7 +707,7 @@
         Utils.setMenuItemVisibility(menu, R.id.move_to, mFolder != null
                 && mFolder.supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION));
         final MenuItem removeFolder = menu.findItem(R.id.remove_folder);
-        if (removeFolder != null) {
+        if (mFolder != null && removeFolder != null) {
             removeFolder.setTitle(mActivity.getApplicationContext().getString(
                     R.string.remove_folder, mFolder.name));
         }
diff --git a/src/com/android/mail/ui/MailActivity.java b/src/com/android/mail/ui/MailActivity.java
index 73a4db3..0bc75da 100644
--- a/src/com/android/mail/ui/MailActivity.java
+++ b/src/com/android/mail/ui/MailActivity.java
@@ -67,7 +67,7 @@
      * to be static since the {@link ComposeActivity} needs to statically change the account name
      * and have the NFC message changed accordingly.
      */
-    private static String sAccountName = null;
+    protected static String sAccountName = null;
 
     /**
      * Create an NFC message (in the NDEF: Nfc Data Exchange Format) to instruct the recepient to
@@ -404,4 +404,10 @@
         mAccessibilityEnabled = enabled;
         mController.onAccessibilityStateChanged();
     }
+
+    @Override
+    public ConversationListHelper getConversationListHelper() {
+        // Unsupported
+        return null;
+    }
 }
diff --git a/src/com/android/mail/ui/MailSpinner.java b/src/com/android/mail/ui/MailSpinner.java
deleted file mode 100644
index 854eeac..0000000
--- a/src/com/android/mail/ui/MailSpinner.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/**
- * Copyright (c) 2012, 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.ui;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.ListPopupWindow;
-import android.widget.TextView;
-
-import com.android.mail.AccountSpinnerAdapter;
-import com.android.mail.R;
-import com.android.mail.providers.Account;
-import com.android.mail.providers.Folder;
-import com.android.mail.utils.LogTag;
-import com.android.mail.utils.LogUtils;
-import com.android.mail.utils.Utils;
-
-public class MailSpinner extends FrameLayout implements OnItemClickListener, OnClickListener {
-    private static final String LOG_TAG = LogTag.getLogTag();
-    private final ListPopupWindow mListPopupWindow;
-    private AccountSpinnerAdapter mSpinnerAdapter;
-    private Account mAccount;
-    private ActivityController mController;
-    private final TextView mAccountName;
-    private final TextView mFolderName;
-    private final TextView mFolderCount;
-    private final LinearLayout mContainer;
-
-    // Created through view inflation.
-    @SuppressWarnings("unused")
-    public MailSpinner(Context context) {
-        this(context, null);
-    }
-
-    public MailSpinner(Context context, AttributeSet attrs) {
-        this(context, attrs, -1);
-    }
-
-    public MailSpinner(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-        mListPopupWindow = new ListPopupWindow(context);
-        mListPopupWindow.setOnItemClickListener(this);
-        mListPopupWindow.setAnchorView(this);
-        final int dropDownWidth = context.getResources().getDimensionPixelSize(
-                R.dimen.account_dropdown_dropdownwidth);
-        mListPopupWindow.setWidth(dropDownWidth);
-        mListPopupWindow.setModal(true);
-        addView(LayoutInflater.from(context).inflate(R.layout.account_switch_spinner_item, null));
-        mAccountName = (TextView) findViewById(R.id.account_second);
-        mFolderName = (TextView) findViewById(R.id.account_first);
-        mFolderCount = (TextView) findViewById(R.id.account_unread);
-        mContainer = (LinearLayout) findViewById(R.id.account_spinner_container);
-        mContainer.setOnClickListener(this);
-    }
-
-    public void setAdapter(AccountSpinnerAdapter adapter) {
-        mSpinnerAdapter = adapter;
-        mListPopupWindow.setAdapter(mSpinnerAdapter);
-    }
-
-    /**
-     * Changes the enabled state of the spinner. Not called {@link #setEnabled(boolean)} because
-     * that is an existing method on views.
-     *
-     * @param enabled true if the spinner allows touch events, and shows a little triangle on the
-     *                bottom right indicating that it is a spinner. False if it is just a view
-     *                showing the account name.
-     */
-    public final void changeEnabledState(boolean enabled) {
-        setEnabled(enabled);
-        if (enabled) {
-            mContainer.setBackgroundResource(R.drawable.spinner_ab_holo_light);
-        } else {
-            mContainer.setBackgroundDrawable(null);
-        }
-    }
-
-    public void setAccount(Account account) {
-        mAccount = account;
-        if (mAccount != null) {
-            mAccountName.setText(mAccount.name);
-        }
-    }
-
-    public void setFolder(Folder folder) {
-        if (folder != null) {
-            mFolderName.setText(folder.name);
-            final int unreadCount = Utils.getFolderUnreadDisplayCount(folder);
-            mFolderCount.setText(Utils.getUnreadCountString(getContext(), unreadCount));
-            mFolderCount.setContentDescription(Utils.formatPlural(getContext(),
-                    R.plurals.unread_mail_count, unreadCount));
-
-            if (mSpinnerAdapter != null) {
-                // Update the spinner with this current folder, as it could change the recent items
-                // that are shown.
-                mSpinnerAdapter.setCurrentFolder(folder);
-            }
-        }
-    }
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        LogUtils.d(LOG_TAG, "onNavigationItemSelected(%d, %d) called", position, id);
-        final int type = mSpinnerAdapter.getItemViewType(position);
-        boolean dismiss = false;
-        switch (type) {
-            case AccountSpinnerAdapter.TYPE_ACCOUNT:
-                // Get the capabilities associated with this account.
-                final Account account = (Account) mSpinnerAdapter.getItem(position);
-                LogUtils.d(LOG_TAG, "onNavigationItemSelected: Selecting account: %s",
-                        account.name);
-                if (mAccount.uri.equals(account.uri)) {
-                    // The selected account is the same, let's load the default inbox.
-                    mController.loadAccountInbox();
-                } else {
-                    // Switching accounts.
-                    mController.onAccountChanged(account);
-                }
-                dismiss = true;
-                break;
-            case AccountSpinnerAdapter.TYPE_FOLDER:
-                final Object folder = mSpinnerAdapter.getItem(position);
-                assert (folder instanceof Folder);
-                LogUtils.d(LOG_TAG, "onNavigationItemSelected: Selecting folder: %s",
-                        ((Folder)folder).name);
-                mController.onFolderChanged((Folder) folder);
-                dismiss = true;
-                break;
-            case AccountSpinnerAdapter.TYPE_ALL_FOLDERS:
-                mController.loadFolderList();
-                dismiss = true;
-                break;
-            case AccountSpinnerAdapter.TYPE_HEADER:
-                LogUtils.e(LOG_TAG, "MailSpinner.onItemClick(): Got unexpected click on header.");
-                break;
-            default:
-                LogUtils.e(LOG_TAG, "MailSpinner.onItemClick(%d): Strange click ignored: type %d.",
-                        position, type);
-                break;
-        }
-        if (dismiss) {
-            mListPopupWindow.dismiss();
-        }
-    }
-
-    public void setController(ActivityController controller) {
-        mController = controller;
-    }
-
-    @Override
-    public void onClick(View arg0) {
-        if (isEnabled() && !mListPopupWindow.isShowing()) {
-            mListPopupWindow.show();
-            // Commit any leave behind items.
-            mController.commitDestructiveActions(false);
-        }
-    }
-
-    public void dismiss() {
-        mListPopupWindow.dismiss();
-    }
-
-    public void onFolderUpdated(Folder folder) {
-        mSpinnerAdapter.onFolderUpdated(folder);
-        setFolder(folder);
-    }
-}
diff --git a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
index 41b0778..cc95a48 100644
--- a/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
+++ b/src/com/android/mail/ui/MultiFoldersSelectionDialog.java
@@ -30,7 +30,6 @@
 import com.android.mail.ui.FolderSelectorAdapter.FolderRow;
 import com.android.mail.utils.Utils;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
@@ -152,7 +151,8 @@
         switch (which) {
             case DialogInterface.BUTTON_POSITIVE:
                 if (mUpdater != null) {
-                    mUpdater.assignFolder(mOperations.values(), mTarget, mBatch, true);
+                    mUpdater.assignFolder(mOperations.values(), mTarget, mBatch,
+                            true /* showUndo */, false /* isMoveTo */);
                 }
                 break;
             case DialogInterface.BUTTON_NEGATIVE:
diff --git a/src/com/android/mail/ui/OnePaneController.java b/src/com/android/mail/ui/OnePaneController.java
index be7193c..fc33b8d 100644
--- a/src/com/android/mail/ui/OnePaneController.java
+++ b/src/com/android/mail/ui/OnePaneController.java
@@ -24,8 +24,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.v4.widget.DrawerLayout;
-import android.support.v4.widget.DrawerLayout.LayoutParams;
-import android.util.Log;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.mail.ConversationListContext;
@@ -59,6 +58,8 @@
     private static final String CONVERSATION_LIST_NEVER_SHOWN_KEY = "conversation-list-never-shown";
     /** Key to store {@link #mInbox}. */
     private final static String SAVED_INBOX_KEY = "m-inbox";
+    /** Set to true to show sections/recent inbox in drawer, false otherwise*/
+    private final static boolean SECTIONS_AND_RECENT_FOLDERS_ENABLED = true;
 
     private static final int INVALID_ID = -1;
     private boolean mConversationListVisible = false;
@@ -146,10 +147,10 @@
      * into drawer (to avoid repetitive calls to replaceFragment).
      */
     @Override
-    public void onAccountChanged(Account account) {
-        super.onAccountChanged(account);
+    public void changeAccount(Account account) {
+        super.changeAccount(account);
         mConversationListNeverShown = true;
-        loadFolderList();
+        resetAndLoadDrawer();
     }
 
     @Override
@@ -166,10 +167,34 @@
         return mConversationListVisible;
     }
 
+    /**
+     * If drawer is open/visible (even partially), close it and replace the
+     * folder fragment upon closing the drawer. Otherwise, the drawer is closed
+     * and we can replace the folder list fragment without concern.
+     */
+    private void resetAndLoadDrawer() {
+        if(mDrawerContainer.isDrawerVisible(mDrawerPullout)) {
+            mDrawerContainer.setDrawerListener(new DrawerLayout.SimpleDrawerListener() {
+                @Override
+                public void onDrawerClosed(View drawerView) {
+                    loadFolderList();
+                    mDrawerContainer.setDrawerListener(null);
+                }
+            });
+            mDrawerContainer.closeDrawers();
+        } else {
+            loadFolderList();
+        }
+    }
+
     @Override
     public void onViewModeChanged(int newMode) {
         super.onViewModeChanged(newMode);
-        mDrawerContainer.closeDrawers();
+
+        // When view mode changes, we should wait for drawer to close and
+        // repopulate folders.
+        resetAndLoadDrawer();
+
         // When entering conversation list mode, hide and clean up any currently visible
         // conversation.
         if (ViewMode.isListMode(newMode)) {
@@ -311,8 +336,10 @@
          * Adding this will enable back stack to labels: mLastFolderListTransactionId =
          */
         replaceFragment(
-                FolderListFragment.newInstance(null, mAccount.folderListUri, false),
-                FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST, R.id.drawer_pullout);
+                FolderListFragment.newInstance(null, mAccount.folderListUri,
+                        SECTIONS_AND_RECENT_FOLDERS_ENABLED, false),
+                FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST,
+                R.id.drawer_pullout);
 
         /*
          * TODO(shahrk): Move or remove this
@@ -428,8 +455,9 @@
             // showing this folder's children if we are not already
             // looking at the child view for this folder.
             mLastFolderListTransactionId = replaceFragment(FolderListFragment.newInstance(
-                    top, top.childFoldersListUri, false),
-                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST, R.id.content_pane);
+                    top, top.childFoldersListUri, SECTIONS_AND_RECENT_FOLDERS_ENABLED, false),
+                    FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST,
+                    R.id.content_pane);
             // Show the up affordance when digging into child folders.
             mActionBarView.setBackButton();
         } else {
@@ -468,7 +496,8 @@
             // showing this folder's children if we are not already
             // looking at the child view for this folder.
             mLastFolderListTransactionId = replaceFragment(
-                    FolderListFragment.newInstance(folder, folder.childFoldersListUri, false),
+                    FolderListFragment.newInstance(folder, folder.childFoldersListUri,
+                            SECTIONS_AND_RECENT_FOLDERS_ENABLED, false),
                     FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_FOLDER_LIST, R.id.content_pane);
             // Show the up affordance when digging into child folders.
             mActionBarView.setBackButton();
@@ -579,7 +608,7 @@
                                     convList != null ? convList.getAnimatedAdapter() : null),
                             0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo,
                             true,  /* replaceVisibleToast */
@@ -593,7 +622,7 @@
                                 getUndoClickedListener(convList.getAnimatedAdapter()),
                                 0,
                                 Utils.convertHtmlToPlainText
-                                    (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                    (op.getDescription(mActivity.getActivityContext())),
                                 true, /* showActionIcon */
                                 R.string.undo,
                                 true,  /* replaceVisibleToast */
diff --git a/src/com/android/mail/ui/RecentFolderList.java b/src/com/android/mail/ui/RecentFolderList.java
index 223ac60..d05530e 100644
--- a/src/com/android/mail/ui/RecentFolderList.java
+++ b/src/com/android/mail/ui/RecentFolderList.java
@@ -18,7 +18,6 @@
 
 import android.content.ContentValues;
 import android.content.Context;
-import android.database.Cursor;
 import android.net.Uri;
 import android.os.AsyncTask;
 
@@ -97,8 +96,8 @@
         /**
          * Create a new asynchronous task to store the recent folder list. Both the account
          * and the folder should be non-null.
-         * @param account
-         * @param folder
+         * @param account the current account for this folder.
+         * @param folder the folder which is to be stored.
          */
         public StoreRecent(Account account, Folder folder) {
             assert (account != null && folder != null);
@@ -124,7 +123,7 @@
     /**
      * Create a Recent Folder List from the given account. This will query the UIProvider to
      * retrieve the RecentFolderList from persistent storage (if any).
-     * @param context
+     * @param context the context for the activity
      */
     public RecentFolderList(Context context) {
         mFolderCache = new LruCache<String, RecentFolderListEntry>(
@@ -134,7 +133,7 @@
 
     /**
      * Initialize the {@link RecentFolderList} with a controllable activity.
-     * @param activity
+     * @param activity the underlying activity
      */
     public void initialize(ControllableActivity activity){
         setCurrentAccount(mAccountObserver.initialize(activity.getAccountController()));
diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java
index 13ab84c..eebec55 100644
--- a/src/com/android/mail/ui/SecureConversationViewFragment.java
+++ b/src/com/android/mail/ui/SecureConversationViewFragment.java
@@ -21,9 +21,6 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
-import android.text.Html;
-import android.text.SpannedString;
-import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,17 +32,16 @@
 
 import com.android.mail.R;
 import com.android.mail.browse.ConversationViewAdapter;
+import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem;
 import com.android.mail.browse.ConversationViewHeader;
 import com.android.mail.browse.MessageCursor;
+import com.android.mail.browse.MessageCursor.ConversationMessage;
 import com.android.mail.browse.MessageFooterView;
 import com.android.mail.browse.MessageHeaderView;
-import com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem;
-import com.android.mail.browse.MessageCursor.ConversationMessage;
 import com.android.mail.browse.MessageHeaderView.MessageHeaderViewCallbacks;
 import com.android.mail.providers.Account;
 import com.android.mail.providers.Conversation;
 import com.android.mail.providers.Message;
-import com.android.mail.providers.UIProvider;
 import com.android.mail.utils.LogTag;
 import com.android.mail.utils.LogUtils;
 
@@ -61,7 +57,7 @@
     private ConversationMessage mMessage;
     private ScrollView mScrollView;
 
-    private WebViewClient mWebViewClient = new AbstractConversationWebViewClient() {
+    private final WebViewClient mWebViewClient = new AbstractConversationWebViewClient() {
         @Override
         public void onPageFinished(WebView view, String url) {
             if (isUserVisible()) {
@@ -100,12 +96,15 @@
         mConversationHeaderView.setCallbacks(this, this);
         mConversationHeaderView.setFoldersVisible(false);
         mConversationHeaderView.setSubject(mConversation.subject);
+        mMessageHeaderView.initialize(mDateBuilder, this, mAddressCache);
+        mMessageHeaderView.setExpandMode(MessageHeaderView.POPUP_MODE);
         mMessageHeaderView.setContactInfoSource(getContactInfoSource());
         mMessageHeaderView.setCallbacks(this);
         mMessageHeaderView.setExpandable(false);
         mMessageHeaderView.setVeiledMatcher(
                 ((ControllableActivity) getActivity()).getAccountController()
                         .getVeiledAddressMatcher());
+        mMessageFooterView.initialize(getLoaderManager(), getFragmentManager());
         getLoaderManager().initLoader(MESSAGE_LOADER, null, getMessageLoaderCallbacks());
         showLoadingStatus();
     }
@@ -161,16 +160,6 @@
     }
 
     @Override
-    public void setMessageSpacerHeight(MessageHeaderItem item, int newSpacerHeight) {
-        // Do nothing.
-    }
-
-    @Override
-    public void setMessageExpanded(MessageHeaderItem item, int newSpacerHeight) {
-        // Do nothing.
-    }
-
-    @Override
     public void onConversationViewHeaderHeightChange(int newHeight) {
         // Do nothing.
     }
@@ -181,12 +170,26 @@
             return;
         }
         if (isUserVisible()) {
-            mScrollView.scrollTo(0, 0);
             onConversationSeen();
         }
     }
 
     @Override
+    public void setMessageSpacerHeight(MessageHeaderItem item, int newSpacerHeight) {
+        // Do nothing.
+    }
+
+    @Override
+    public void setMessageExpanded(MessageHeaderItem item, int newSpacerHeight) {
+        // Do nothing.
+    }
+
+    @Override
+    public void setMessageDetailsExpanded(MessageHeaderItem i, boolean expanded, int heightbefore) {
+        // Do nothing.
+    }
+
+    @Override
     public void showExternalResources(final Message msg) {
         mWebView.getSettings().setBlockNetworkImage(false);
     }
@@ -197,6 +200,16 @@
     }
 
     @Override
+    public boolean supportsMessageTransforms() {
+        return false;
+    }
+
+    @Override
+    public String getMessageTransforms(final Message msg) {
+        return null;
+    }
+
+    @Override
     protected void onMessageCursorLoadFinished(Loader<Cursor> loader, MessageCursor newCursor,
             MessageCursor oldCursor) {
         // ignore cursors that are still loading results
@@ -208,7 +221,7 @@
             // Activity is finishing, just bail.
             return;
         }
-        renderMessageBodies(newCursor, mEnableContentReadySignal);
+        renderMessageBodies(newCursor);
     }
 
     /**
@@ -216,35 +229,23 @@
      * blocks, a conversation header), and return an HTML document with spacer
      * divs inserted for all overlays.
      */
-    private void renderMessageBodies(MessageCursor messageCursor,
-            boolean enableContentReadySignal) {
-        final StringBuilder convHtml = new StringBuilder();
-        String content;
-        if (messageCursor.moveToFirst()) {
-            content = messageCursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN);
-            if (TextUtils.isEmpty(content)) {
-                content = messageCursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN);
-                if (content != null) {
-                    content = Html.toHtml(new SpannedString(content));
-                }
-            }
-            convHtml.append(content);
-            mMessage = messageCursor.getMessage();
-            mWebView.getSettings().setBlockNetworkImage(!mMessage.alwaysShowImages);
-            mWebView.loadDataWithBaseURL(mBaseUri, convHtml.toString(), "text/html", "utf-8", null);
-            ConversationViewAdapter mAdapter = new ConversationViewAdapter(mActivity, null, null,
-                    null, null, null, null, null, null);
-            MessageHeaderItem item = mAdapter.newMessageHeaderItem(mMessage, true,
-                    mMessage.alwaysShowImages);
-            mMessageHeaderView.initialize(mDateBuilder, this, mAddressCache);
-            mMessageHeaderView.setExpandMode(MessageHeaderView.POPUP_MODE);
-            mMessageHeaderView.bind(item, false);
-            mMessageHeaderView.setMessageDetailsVisibility(View.VISIBLE);
-            if (mMessage.hasAttachments) {
-                mMessageFooterView.setVisibility(View.VISIBLE);
-                mMessageFooterView.initialize(getLoaderManager(), getFragmentManager());
-                mMessageFooterView.bind(item, false);
-            }
+    private void renderMessageBodies(MessageCursor messageCursor) {
+        if (!messageCursor.moveToFirst()) {
+            LogUtils.e(LOG_TAG, "unable to open message cursor");
+            return;
+        }
+        final ConversationMessage m = messageCursor.getMessage();
+        mMessage = messageCursor.getMessage();
+        mWebView.getSettings().setBlockNetworkImage(!mMessage.alwaysShowImages);
+        mWebView.loadDataWithBaseURL(mBaseUri, m.getBodyAsHtml(), "text/html", "utf-8", null);
+        final ConversationViewAdapter adapter = new ConversationViewAdapter(mActivity, null, null,
+                null, null, null, null, null, null);
+        final MessageHeaderItem item = adapter.newMessageHeaderItem(mMessage, true,
+                mMessage.alwaysShowImages);
+        mMessageHeaderView.bind(item, false);
+        if (mMessage.hasAttachments) {
+            mMessageFooterView.setVisibility(View.VISIBLE);
+            mMessageFooterView.bind(item, false);
         }
     }
 
@@ -257,8 +258,4 @@
         }
     }
 
-    @Override
-    public void setMessageDetailsExpanded(MessageHeaderItem i, boolean expanded, int heightbefore) {
-        // Do nothing.
-    }
 }
diff --git a/src/com/android/mail/ui/SingleFolderSelectionDialog.java b/src/com/android/mail/ui/SingleFolderSelectionDialog.java
index 7676732..f7c5771 100644
--- a/src/com/android/mail/ui/SingleFolderSelectionDialog.java
+++ b/src/com/android/mail/ui/SingleFolderSelectionDialog.java
@@ -71,11 +71,12 @@
             // Currently, the number of adapters are assumed to match the
             // number of headers in the string array.
             mAdapter.addSection(new SystemFolderSelectorAdapter(context, foldersCursor,
-                    R.layout.single_folders_view, null, mCurrentFolder));
+                    R.layout.single_folders_view, headers[0], mCurrentFolder));
 
             // TODO(mindyp): we currently do not support frequently moved to
             // folders, at headers[1]; need to define what that means.*/
-            mAdapter.addSection(new HierarchicalFolderSelectorAdapter(context,
+            // TODO(pwestbro): determine if we need to call filterFolders
+            mAdapter.addSection(new UserFolderHierarchicalFolderSelectorAdapter(context,
                     AddableFolderSelectorAdapter.filterFolders(foldersCursor),
                     R.layout.single_folders_view, headers[2], mCurrentFolder));
             mBuilder.setAdapter(mAdapter, SingleFolderSelectionDialog.this);
@@ -95,7 +96,7 @@
             // Remove the current folder and add the new folder.
             ops.add(new FolderOperation(mCurrentFolder, false));
             ops.add(new FolderOperation(folder, true));
-            mUpdater.assignFolder(ops, mTarget, mBatch, true);
+            mUpdater.assignFolder(ops, mTarget, mBatch, true /* showUndo */, true /* isMoveTo */);
             mDialog.dismiss();
         }
     }
diff --git a/src/com/android/mail/ui/SwipeableListView.java b/src/com/android/mail/ui/SwipeableListView.java
index 4048119..82d4d33 100644
--- a/src/com/android/mail/ui/SwipeableListView.java
+++ b/src/com/android/mail/ui/SwipeableListView.java
@@ -196,7 +196,8 @@
         final Context context = getContext();
         final ToastBarOperation undoOp;
 
-        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false);
+        undoOp = new ToastBarOperation(1, mSwipeAction, ToastBarOperation.UNDO, false /* batch */,
+                mFolder);
         Conversation conv = target.getConversation();
         target.getConversation().position = findConversation(target, conv);
         final AnimatedAdapter adapter = getAnimatedAdapter();
diff --git a/src/com/android/mail/ui/ToastBarOperation.java b/src/com/android/mail/ui/ToastBarOperation.java
index b56a94d..b47879f 100644
--- a/src/com/android/mail/ui/ToastBarOperation.java
+++ b/src/com/android/mail/ui/ToastBarOperation.java
@@ -33,19 +33,25 @@
     private final int mCount;
     private final boolean mBatch;
     private final int mType;
+    private final Folder mFolder;
 
     /**
      * Create a ToastBarOperation
      *
      * @param count Number of conversations this action would be applied to.
-     * @param menuId res id identifying the menu item tapped; used to determine
-     *            what action was performed
+     * @param menuId res id identifying the menu item tapped; used to determine what action was
+     *        performed
+     * @param operationFolder The {@link Folder} upon which the operation was run. This may be
+     *        <code>null</code>, but is required in {@link #getDescription(Context)} for certain
+     *        actions.
      */
-    public ToastBarOperation(int count, int menuId, int type, boolean batch) {
+    public ToastBarOperation(int count, int menuId, int type, boolean batch,
+            final Folder operationFolder) {
         mCount = count;
         mAction = menuId;
         mBatch = batch;
         mType = type;
+        mFolder = operationFolder;
     }
 
     public int getType() {
@@ -56,11 +62,12 @@
         return mBatch;
     }
 
-    public ToastBarOperation(Parcel in) {
+    public ToastBarOperation(final Parcel in, final ClassLoader loader) {
         mCount = in.readInt();
         mAction = in.readInt();
         mBatch = in.readInt() != 0;
         mType = in.readInt();
+        mFolder = in.readParcelable(loader);
     }
 
     @Override
@@ -69,35 +76,44 @@
         dest.writeInt(mAction);
         dest.writeInt(mBatch ? 1 : 0);
         dest.writeInt(mType);
+        dest.writeParcelable(mFolder, 0);
     }
 
-    public static final Creator<ToastBarOperation> CREATOR = new Creator<ToastBarOperation>() {
+    public static final ClassLoaderCreator<ToastBarOperation> CREATOR =
+            new ClassLoaderCreator<ToastBarOperation>() {
         @Override
-        public ToastBarOperation createFromParcel(Parcel source) {
-            return new ToastBarOperation(source);
+        public ToastBarOperation createFromParcel(final Parcel source) {
+            return createFromParcel(source, null);
         }
 
         @Override
-        public ToastBarOperation[] newArray(int size) {
+        public ToastBarOperation[] newArray(final int size) {
             return new ToastBarOperation[size];
         }
+
+        @Override
+        public ToastBarOperation createFromParcel(final Parcel source, final ClassLoader loader) {
+            return new ToastBarOperation(source, loader);
+        }
     };
 
     /**
      * Get a string description of the operation that will be performed
      * when the user taps the undo bar.
      */
-    public String getDescription(Context context, Folder folder) {
+    public String getDescription(Context context) {
         int resId = -1;
         switch (mAction) {
             case R.id.delete:
                 resId = R.plurals.conversation_deleted;
                 break;
             case R.id.remove_folder:
-                return context.getString(R.string.folder_removed, folder.name);
+                return context.getString(R.string.folder_removed, mFolder.name);
             case R.id.change_folder:
                 resId = R.plurals.conversation_folder_changed;
                 break;
+            case R.id.move_folder:
+                return context.getString(R.string.conversation_folder_moved, mFolder.name);
             case R.id.archive:
                 resId = R.plurals.conversation_archived;
                 break;
diff --git a/src/com/android/mail/ui/TwoPaneController.java b/src/com/android/mail/ui/TwoPaneController.java
index 418ee75..d022352 100644
--- a/src/com/android/mail/ui/TwoPaneController.java
+++ b/src/com/android/mail/ui/TwoPaneController.java
@@ -105,7 +105,8 @@
     private void createFolderListFragment(Folder parent, Uri uri) {
         setHierarchyFolder(parent);
         // Create a sectioned FolderListFragment.
-        FolderListFragment folderListFragment = FolderListFragment.newInstance(parent, uri, true);
+        FolderListFragment folderListFragment = FolderListFragment.newInstance(parent, uri, true,
+                true);
         FragmentTransaction fragmentTransaction = mActivity.getFragmentManager().beginTransaction();
         if (Utils.useFolderListFragmentTransition(mActivity.getActivityContext())) {
             fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
@@ -163,8 +164,8 @@
     }
 
     @Override
-    public void onAccountChanged(Account account) {
-        super.onAccountChanged(account);
+    public void changeAccount(Account account) {
+        super.changeAccount(account);
         renderFolderList();
     }
 
@@ -473,7 +474,7 @@
                             getUndoClickedListener(convList.getAnimatedAdapter()),
                             0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo,
                             true,  /* replaceVisibleToast */
@@ -485,7 +486,7 @@
                 if (convList != null) {
                     mToastBar.show(getUndoClickedListener(convList.getAnimatedAdapter()), 0,
                             Utils.convertHtmlToPlainText
-                                (op.getDescription(mActivity.getActivityContext(), mFolder)),
+                                (op.getDescription(mActivity.getActivityContext())),
                             true, /* showActionIcon */
                             R.string.undo, true, /* replaceVisibleToast */
                             op);
diff --git a/src/com/android/mail/ui/UserFolderHierarchicalFolderSelectorAdapter.java b/src/com/android/mail/ui/UserFolderHierarchicalFolderSelectorAdapter.java
new file mode 100644
index 0000000..9a601cf
--- /dev/null
+++ b/src/com/android/mail/ui/UserFolderHierarchicalFolderSelectorAdapter.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ *      Copyright (C) 2013 Google Inc.
+ *      Licensed to The Android Open Source Project.
+ *
+ *      Licensed under the Apache License, Version 2.0 (the "License");
+ *      you may not use this file except in compliance with the License.
+ *      You may obtain a copy of the License at
+ *
+ *           http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *      Unless required by applicable law or agreed to in writing, software
+ *      distributed under the License is distributed on an "AS IS" BASIS,
+ *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *      See the License for the specific language governing permissions and
+ *      limitations under the License.
+ *******************************************************************************/
+package com.android.mail.ui;
+
+import android.content.Context;
+import android.database.Cursor;
+import com.android.mail.providers.Folder;
+
+import java.util.Set;
+
+public class UserFolderHierarchicalFolderSelectorAdapter extends HierarchicalFolderSelectorAdapter {
+    public UserFolderHierarchicalFolderSelectorAdapter(Context context, Cursor folders, int layout,
+                                                       String header, Folder excludedFolder) {
+        super(context, folders, layout, header, excludedFolder);
+    }
+
+    /**
+     * Return whether the supplied folder meets the requirements to be displayed
+     * in the folder list.
+     */
+    @Override
+    protected boolean meetsRequirements(Folder folder) {
+        if (folder.isProviderFolder()) {
+            return false;
+        }
+        return super.meetsRequirements(folder);
+    }
+}
diff --git a/src/com/android/mail/utils/NotificationUtils.java b/src/com/android/mail/utils/NotificationUtils.java
index 2f72e44..dbc0113 100644
--- a/src/com/android/mail/utils/NotificationUtils.java
+++ b/src/com/android/mail/utils/NotificationUtils.java
@@ -708,11 +708,14 @@
                                     UIProvider.MESSAGE_PROJECTION, null, null, null);
                             messageCursor = new MessageCursor(cursor);
 
-                            String from = null;
+                            String from = "";
                             String fromAddress = "";
                             if (messageCursor.moveToPosition(messageCursor.getCount() - 1)) {
                                 final Message message = messageCursor.getMessage();
                                 fromAddress = message.getFrom();
+                                if (fromAddress == null) {
+                                    fromAddress = "";
+                                }
                                 from = getDisplayableSender(fromAddress);
                             }
                             while (messageCursor.moveToPosition(messageCursor.getPosition() - 1)) {
diff --git a/src/com/android/mail/utils/Observable.java b/src/com/android/mail/utils/Observable.java
new file mode 100644
index 0000000..81e8d83
--- /dev/null
+++ b/src/com/android/mail/utils/Observable.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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.database.DataSetObservable;
+import android.database.DataSetObserver;
+
+/**
+ * A Utility class to register observers and return logging and counts for the number of registered
+ * observers.
+ */
+public class Observable extends DataSetObservable {
+    protected static final String LOG_TAG = LogTag.getLogTag();
+    private final String mName;
+
+    public Observable(String name) {
+        mName = name;
+    }
+
+    @Override
+    public void registerObserver(DataSetObserver observer) {
+        final int count = mObservers.size();
+        super.registerObserver(observer);
+        LogUtils.d(LOG_TAG, "IN register(%s)Observer: %s before=%d after=%d",
+                mName,  observer, count, mObservers.size());
+    }
+
+    @Override
+    public void unregisterObserver(DataSetObserver observer) {
+        final int count = mObservers.size();
+        super.unregisterObserver(observer);
+        LogUtils.d(LOG_TAG, "IN unregister(%s)Observer: %s before=%d after=%d",
+                mName, observer, count, mObservers.size());
+    }
+}
diff --git a/unified_src/com/android/mail/providers/protos/boot/AccountReceiver.java b/unified_src/com/android/mail/providers/protos/boot/AccountReceiver.java
deleted file mode 100644
index 9e2412f..0000000
--- a/unified_src/com/android/mail/providers/protos/boot/AccountReceiver.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Copyright (c) 2011, 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.boot;
-
-import com.android.mail.providers.protos.mock.MockUiProvider;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-
-public class AccountReceiver extends BroadcastReceiver {
-    /**
-     * Intent used to notify interested parties that the Mail provider has been created.
-     */
-    public static final String ACTION_PROVIDER_CREATED
-            = "com.android.mail.providers.protos.boot.intent.ACTION_PROVIDER_CREATED";
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        MockUiProvider.initializeMockProvider();
-    }
-}