am 933e297f: am 15333d64: am b5d8d228: am 030f1bdf: Merge "New keyboard shortcuts" into ub-gmail-ur14-dev
* commit '933e297f00298b14cffa4d8b7807c29b45892213':
New keyboard shortcuts
diff --git a/res/menu-sw600dp-land/conversation_actions.xml b/res/menu-sw600dp-land/conversation_actions.xml
index 3819f48..4937b39 100644
--- a/res/menu-sw600dp-land/conversation_actions.xml
+++ b/res/menu-sw600dp-land/conversation_actions.xml
@@ -24,22 +24,23 @@
android:title="@string/archive"
app:showAsAction="always"
android:icon="@drawable/ic_archive_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char" />
+ android:alphabeticShortcut="@string/trigger_archive_char" />
<item
android:id="@+id/remove_folder"
android:title="@string/remove_folder"
app:showAsAction="always"
android:icon="@drawable/ic_remove_label_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_archive_char" />
<!-- Depends on FolderCapabilities.DELETE -->
<item
android:id="@+id/delete"
android:title="@string/delete"
app:showAsAction="always"
- android:icon="@drawable/ic_delete_wht_24dp" />
+ android:icon="@drawable/ic_delete_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Depends on the user viewing a draft label, and the above menu item not being shown -->
<item
@@ -47,14 +48,16 @@
android:title="@string/discard_drafts"
app:showAsAction="always"
android:icon="@drawable/ic_delete_wht_24dp"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Depends on the user viewing a outbox label and the setting supports delete -->
<item
android:id="@+id/discard_outbox"
android:title="@string/discard_failed"
app:showAsAction="always"
android:icon="@drawable/ic_delete_wht_24dp"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<item
android:id="@+id/inside_conversation_unread"
@@ -73,7 +76,8 @@
android:id="@+id/change_folders"
android:title="@string/menu_change_folders"
app:showAsAction="never"
- android:icon="@drawable/ic_change_labels_wht_24dp" />
+ android:icon="@drawable/ic_change_labels_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_change_label_char" />
<item
android:id="@+id/move_to_inbox"
@@ -97,8 +101,9 @@
app:showAsAction="never" />
<item android:id="@+id/print_all"
- android:title="@string/print_all"
- android:visible="false" />
+ android:title="@string/print_all"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_print_char" />
<item
android:id="@+id/show_original"
@@ -136,4 +141,40 @@
android:visible="false"
android:alphabeticShortcut="@string/trigger_refresh_char" />
+ <item
+ android:id="@+id/reply"
+ android:title="@string/reply"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_reply_char" />
+
+ <item
+ android:id="@+id/reply_all"
+ android:title="@string/reply_all"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_reply_all_char" />
+
+ <item
+ android:id="@+id/toggle_read_unread"
+ android:title="@string/toggle_read_unread"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_read_unread_char" />
+
+ <item
+ android:id="@+id/toggle_drawer"
+ android:title="@string/menu_toggle_drawer"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_drawer_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
+
</menu>
diff --git a/res/menu-sw600dp-land/conversation_list_search_results_actions.xml b/res/menu-sw600dp-land/conversation_list_search_results_actions.xml
index 6f813a1..412de85 100644
--- a/res/menu-sw600dp-land/conversation_list_search_results_actions.xml
+++ b/res/menu-sw600dp-land/conversation_list_search_results_actions.xml
@@ -22,7 +22,8 @@
android:id="@+id/delete"
android:title="@string/delete"
app:showAsAction="always"
- android:icon="@drawable/ic_delete_wht_24dp" />
+ android:icon="@drawable/ic_delete_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<item
android:id="@+id/inside_conversation_unread"
@@ -34,7 +35,8 @@
android:id="@+id/change_folders"
android:title="@string/menu_change_folders"
app:showAsAction="never"
- android:icon="@drawable/ic_change_labels_wht_24dp" />
+ android:icon="@drawable/ic_change_labels_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_change_label_char" />
<item
android:id="@+id/mark_important"
@@ -58,9 +60,34 @@
android:visible="false"
android:alphabeticShortcut="@string/trigger_compose_char" />
- <item android:id="@+id/refresh"
+ <item
+ android:id="@+id/refresh"
android:title="@string/refresh"
android:visible="false"
android:alphabeticShortcut="@string/trigger_refresh_char" />
+ <item
+ android:id="@+id/toggle_read_unread"
+ android:title="@string/toggle_read_unread"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_read_unread_char" />
+
+ <item
+ android:id="@+id/toggle_drawer"
+ android:title="@string/menu_toggle_drawer"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_drawer_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
+
</menu>
diff --git a/res/menu/account_feedback_menu.xml b/res/menu/account_feedback_menu.xml
index 81e0ddf..4789bb3 100644
--- a/res/menu/account_feedback_menu.xml
+++ b/res/menu/account_feedback_menu.xml
@@ -24,7 +24,8 @@
android:id="@+id/settings"
android:title="@string/menu_settings"
android:menuCategory="secondary"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
<!-- Available if the account specifies a help url -->
<item
@@ -32,5 +33,6 @@
android:icon="@android:drawable/ic_menu_help"
android:menuCategory="secondary"
app:showAsAction="never"
- android:title="@string/help_and_feedback" />
+ android:title="@string/help_and_feedback"
+ android:alphabeticShortcut="@string/trigger_help_char" />
</menu>
\ No newline at end of file
diff --git a/res/menu/compose_menu.xml b/res/menu/compose_menu.xml
index 693afdc..31663e2 100644
--- a/res/menu/compose_menu.xml
+++ b/res/menu/compose_menu.xml
@@ -47,22 +47,26 @@
<item android:id="@+id/send"
android:icon="@drawable/ic_send_wht_24dp"
android:title="@string/send"
- app:showAsAction="always" />
+ app:showAsAction="always"
+ android:alphabeticShortcut="@string/trigger_send_char" />
<item android:id="@+id/save"
android:title="@string/save_draft"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_save_char" />
<item android:id="@+id/discard"
android:title="@string/discard"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<item android:id="@+id/settings"
android:title="@string/menu_settings"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
- <item
- android:id="@+id/help_info_menu_item"
- android:title="@string/help_and_feedback" />
+ <item android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:alphabeticShortcut="@string/trigger_help_char" />
</menu>
diff --git a/res/menu/conversation_actions.xml b/res/menu/conversation_actions.xml
index 53efb5a..620169a 100644
--- a/res/menu/conversation_actions.xml
+++ b/res/menu/conversation_actions.xml
@@ -25,22 +25,23 @@
android:title="@string/archive"
app:showAsAction="always"
android:icon="@drawable/ic_archive_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char" />
+ android:alphabeticShortcut="@string/trigger_archive_char" />
<item
android:id="@+id/remove_folder"
android:title="@string/remove_folder"
app:showAsAction="always"
android:icon="@drawable/ic_remove_label_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_archive_char" />
<!-- Depends on FolderCapabilities.DELETE -->
<item
android:id="@+id/delete"
android:title="@string/delete"
app:showAsAction="always"
- android:icon="@drawable/ic_delete_wht_24dp" />
+ android:icon="@drawable/ic_delete_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Depends on the user viewing a draft label, and the above menu item not being shown -->
<item
@@ -48,14 +49,16 @@
android:title="@string/discard_drafts"
app:showAsAction="always"
android:icon="@drawable/ic_delete_wht_24dp"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Depends on the user viewing a outbox label and the setting supports delete -->
<item
android:id="@+id/discard_outbox"
android:title="@string/discard_failed"
app:showAsAction="always"
android:icon="@drawable/ic_delete_wht_24dp"
- android:visible="false" />
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Always available -->
<item
@@ -76,7 +79,8 @@
android:id="@+id/change_folders"
android:title="@string/menu_change_folders"
app:showAsAction="never"
- android:icon="@drawable/ic_change_labels_wht_24dp" />
+ android:icon="@drawable/ic_change_labels_wht_24dp"
+ android:alphabeticShortcut="@string/trigger_change_label_char" />
<item
android:id="@+id/move_to_inbox"
@@ -101,8 +105,9 @@
android:title="@string/mute" />
<item android:id="@+id/print_all"
- android:title="@string/print_all"
- android:visible="false" />
+ android:title="@string/print_all"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_print_char" />
<item
android:id="@+id/show_original"
@@ -123,4 +128,47 @@
android:title="@string/report_phishing"
android:visible="false" />
+ <!-- These invisible menu items are used to enable keyboard shortcuts -->
+ <item
+ android:id="@+id/compose"
+ android:title="@string/menu_compose"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_compose_char" />
+
+ <item
+ android:id="@+id/reply"
+ android:title="@string/reply"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_reply_char" />
+
+ <item
+ android:id="@+id/reply_all"
+ android:title="@string/reply_all"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_reply_all_char" />
+
+ <item
+ android:id="@+id/toggle_read_unread"
+ android:title="@string/toggle_read_unread"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_read_unread_char" />
+
+ <item
+ android:id="@+id/toggle_drawer"
+ android:title="@string/menu_toggle_drawer"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_drawer_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
+
</menu>
diff --git a/res/menu/conversation_list_menu.xml b/res/menu/conversation_list_menu.xml
index fc4896a..3d574d6 100644
--- a/res/menu/conversation_list_menu.xml
+++ b/res/menu/conversation_list_menu.xml
@@ -23,13 +23,15 @@
<item
android:id="@+id/empty_trash"
android:title="@string/empty_trash"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Available only in the spam folder, when the account supports emptying it -->
<item
android:id="@+id/empty_spam"
android:title="@string/empty_spam"
- app:showAsAction="never" />
+ app:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_delete_char" />
<!-- Available only for accounts with SERVER_SEARCH and in a folder
that supports FOLDER_SERVER_SEARCH -->
@@ -45,9 +47,33 @@
android:visible="false"
android:alphabeticShortcut="@string/trigger_compose_char" />
- <item android:id="@+id/refresh"
+ <item
+ android:id="@+id/refresh"
android:title="@string/refresh"
android:visible="false"
android:alphabeticShortcut="@string/trigger_refresh_char" />
+ <item
+ android:id="@+id/toggle_read_unread"
+ android:title="@string/toggle_read_unread"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_read_unread_char" />
+
+ <item
+ android:id="@+id/toggle_drawer"
+ android:title="@string/menu_toggle_drawer"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_drawer_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
</menu>
diff --git a/res/menu/conversation_list_search_results_actions.xml b/res/menu/conversation_list_search_results_actions.xml
index 662c1e8..337f2c9 100644
--- a/res/menu/conversation_list_search_results_actions.xml
+++ b/res/menu/conversation_list_search_results_actions.xml
@@ -26,9 +26,28 @@
android:visible="false"
android:alphabeticShortcut="@string/trigger_compose_char" />
- <item android:id="@+id/refresh"
+ <item
+ android:id="@+id/refresh"
android:title="@string/refresh"
android:visible="false"
android:alphabeticShortcut="@string/trigger_refresh_char" />
+ <item
+ android:id="@+id/toggle_read_unread"
+ android:title="@string/toggle_read_unread"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_read_unread_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
+
</menu>
diff --git a/res/menu/conversation_list_selection_actions_menu.xml b/res/menu/conversation_list_selection_actions_menu.xml
index ac8f050..0aa811e 100644
--- a/res/menu/conversation_list_selection_actions_menu.xml
+++ b/res/menu/conversation_list_selection_actions_menu.xml
@@ -24,15 +24,13 @@
android:id="@+id/archive"
android:title="@string/archive"
app:showAsAction="always"
- android:icon="@drawable/ic_archive_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char"/>
+ android:icon="@drawable/ic_archive_wht_24dp" />
<item
android:id="@+id/remove_folder"
android:title="@string/remove_folder"
app:showAsAction="always"
android:icon="@drawable/ic_remove_label_wht_24dp"
- android:alphabeticShortcut="@string/trigger_y_char"
android:visible="false" />
<!-- Depends on FolderCapabilities.DELETE -->
@@ -40,7 +38,7 @@
android:id="@+id/delete"
android:title="@string/delete"
app:showAsAction="always"
- android:icon="@drawable/ic_delete_wht_24dp"/>
+ android:icon="@drawable/ic_delete_wht_24dp" />
<!-- Depends on the user viewing a draft label, and the above menu item not being shown -->
<item
diff --git a/res/menu/eml_fragment_menu.xml b/res/menu/eml_fragment_menu.xml
index 11624f0..3efcf07 100644
--- a/res/menu/eml_fragment_menu.xml
+++ b/res/menu/eml_fragment_menu.xml
@@ -18,7 +18,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/print_message"
- android:title="@string/print"
- android:showAsAction="never" />
-
+ android:title="@string/print"
+ android:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_print_char" />
</menu>
\ No newline at end of file
diff --git a/res/menu/general_prefs_fragment_menu.xml b/res/menu/general_prefs_fragment_menu.xml
index 030c765..5b2e9d9 100644
--- a/res/menu/general_prefs_fragment_menu.xml
+++ b/res/menu/general_prefs_fragment_menu.xml
@@ -30,7 +30,8 @@
<item
android:id="@+id/help_info_menu_item"
android:icon="@android:drawable/ic_menu_help"
- android:title="@string/help_and_feedback"/>
+ android:title="@string/help_and_feedback"
+ android:alphabeticShortcut="@string/trigger_help_char" />
<!-- TODO add help menu item, once help support has been moved to UnifiedEmail -->
</menu>
diff --git a/res/menu/help_menu.xml b/res/menu/help_menu.xml
index d7d1d29..9994e47 100644
--- a/res/menu/help_menu.xml
+++ b/res/menu/help_menu.xml
@@ -21,7 +21,8 @@
android:showAsAction="never"/>
<item android:id="@+id/print_dialog"
android:title="@string/print_dialog"
- android:showAsAction="never"/>
+ android:showAsAction="never"
+ android:alphabeticShortcut="@string/trigger_print_char" />
<item android:id="@+id/copyright_information"
android:title="@string/copyright_information"
android:showAsAction="never"/>
diff --git a/res/menu/photo_view_menu.xml b/res/menu/photo_view_menu.xml
index 3969575..9d15daa 100644
--- a/res/menu/photo_view_menu.xml
+++ b/res/menu/photo_view_menu.xml
@@ -21,7 +21,8 @@
<item
android:id="@+id/menu_save"
android:showAsAction="never"
- android:title="@string/save_attachment"/>
+ android:title="@string/save_attachment"
+ android:alphabeticShortcut="@string/trigger_save_char" />
<item
android:id="@+id/menu_save_all"
android:showAsAction="never"
@@ -41,7 +42,8 @@
<item
android:id="@+id/menu_print"
android:showAsAction="never"
- android:title="@string/menu_photo_print"/>
+ android:title="@string/menu_photo_print"
+ android:alphabeticShortcut="@string/trigger_print_char" />
<item
android:id="@+id/menu_download_again"
android:showAsAction="never"
diff --git a/res/menu/vacation_responder_menu.xml b/res/menu/vacation_responder_menu.xml
index 184b24d..35b0c1f 100644
--- a/res/menu/vacation_responder_menu.xml
+++ b/res/menu/vacation_responder_menu.xml
@@ -17,12 +17,10 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_cancel"
- android:alphabeticShortcut="c"
android:title="@string/cancel"
android:icon="@drawable/ic_cancel_holo_light"
app:showAsAction="withText|always" />
<item android:id="@+id/action_done"
- android:alphabeticShortcut="d"
android:title="@string/done"
android:icon="@drawable/ic_menu_done_holo_light"
app:showAsAction="withText|always" />
diff --git a/res/menu/wait_mode_actions.xml b/res/menu/wait_mode_actions.xml
index 65314ab..75a8ed1 100644
--- a/res/menu/wait_mode_actions.xml
+++ b/res/menu/wait_mode_actions.xml
@@ -23,4 +23,21 @@
android:visible="false"
android:alphabeticShortcut="@string/trigger_refresh_char" />
+ <item
+ android:id="@+id/toggle_drawer"
+ android:title="@string/menu_toggle_drawer"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_toggle_drawer_char" />
+
+ <item
+ android:id="@+id/settings"
+ android:title="@string/menu_settings"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_settings_char" />
+
+ <item
+ android:id="@+id/help_info_menu_item"
+ android:title="@string/help_and_feedback"
+ android:visible="false"
+ android:alphabeticShortcut="@string/trigger_help_char" />
</menu>
diff --git a/res/values/shortcut_keys.xml b/res/values/shortcut_keys.xml
index c360f51..78be21d 100644
--- a/res/values/shortcut_keys.xml
+++ b/res/values/shortcut_keys.xml
@@ -15,15 +15,39 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+<resources>
+ <!-- All shortcuts need to be combined with CTRL -->
- <!-- Character, that when combined with CTRL, should cause a save action -->
+ <!-- open compose -->
+ <string name="trigger_compose_char" translatable="false">n</string>
+ <!-- archive, can also be remove folder when archive is not applicable -->
+ <string name="trigger_archive_char" translatable="false">d</string>
+ <!-- delete (\u0008 is BACKSPACE), can also be clear trash/spam -->
+ <!-- TODO: there is a separate ASCII for DEL, should we support that? -->
+ <string name="trigger_delete_char" translatable="false">\u0008</string>
+ <!-- send (TODO: looks like edittext is consuming this event) -->
+ <string name="trigger_send_char" translatable="false">\u000a</string>
+ <!-- save draft -->
<string name="trigger_save_char" translatable="false">s</string>
- <!-- Character, that when combined with CTRL, should open compose -->
- <string name="trigger_compose_char" translatable="false">c</string>
- <!-- Character, that when combined with CTRL, should trigger a refresh -->
+ <!-- manual refresh -->
<string name="trigger_refresh_char" translatable="false">u</string>
- <!-- Character, that when combined with CTRL, should trigger the Y button action (sometimes archive, sometimes delete, etc) -->
- <string name="trigger_y_char" translatable="false">y</string>
+ <!-- open navigation drawer -->
+ <string name="trigger_toggle_drawer_char" translatable="false">m</string>
+ <!-- Settings -->
+ <string name="trigger_settings_char" translatable="false">,</string>
+ <!-- Help & Feedback -->
+ <string name="trigger_help_char" translatable="false">/</string>
+ <!-- reply TODO -->
+ <string name="trigger_reply_char" translatable="false">`</string>
+ <!-- reply all -->
+ <string name="trigger_reply_all_char" translatable="false">r</string>
+ <!-- mark as read/unread -->
+ <string name="trigger_toggle_read_unread_char" translatable="false">i</string>
+ <!-- change label -->
+ <string name="trigger_change_label_char" translatable="false">l</string>
+ <!-- print -->
+ <string name="trigger_print_char" translatable="false">p</string>
+ <!-- undo in snack bar TODO punted -->
+ <string name="trigger_undo_char" translatable="false">z</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0cf62c3..29d8a91 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -108,6 +108,8 @@
<string name="mark_read">Mark read</string>
<!-- Menu item: mark this conversation as unread -->
<string name="mark_unread">Mark unread</string>
+ <!-- Menu item: toggle read/unread for menus that contain both read and unread options -->
+ <string name="toggle_read_unread">Toggle read unread</string>
<!-- Menu item: mute this conversation -->
<string name="mute">Mute</string>
<!-- Menu item: add a star to this conversation -->
@@ -171,6 +173,8 @@
<string name="menu_settings">Settings</string>
<!-- Menu item: search through the Gmail inbox -->
<string name="menu_search">Search</string>
+ <!-- Menu item: toggle drawer -->
+ <string name="menu_toggle_drawer">Toggle drawer</string>
<!-- Title of the drawer, indicating what it is used for, which is navigation of the app -->
<string name="drawer_title">Navigation</string>
diff --git a/src/com/android/mail/analytics/AnalyticsUtils.java b/src/com/android/mail/analytics/AnalyticsUtils.java
index b968ad7..4d16e30 100644
--- a/src/com/android/mail/analytics/AnalyticsUtils.java
+++ b/src/com/android/mail/analytics/AnalyticsUtils.java
@@ -46,12 +46,12 @@
s = "report_spam";
} else if (id == R.id.mark_not_spam) {
s = "mark_not_spam";
- } else if (id == R.id.report_phishing) {
- s = "report_phishing";
} else if (id == R.id.compose) {
s = "compose";
} else if (id == R.id.refresh) {
s = "refresh";
+ } else if (id == R.id.toggle_drawer) {
+ s = "toggle_drawer";
} else if (id == R.id.settings) {
s = "settings";
} else if (id == R.id.help_info_menu_item) {
@@ -76,6 +76,8 @@
s = "mark_read";
} else if (id == R.id.unread) {
s = "mark_unread";
+ } else if (id == R.id.toggle_read_unread) {
+ s = "toggle_read_unread";
} else if (id == R.id.show_original) {
s = "show_original";
} else if (id == R.id.add_file_attachment) {
diff --git a/src/com/android/mail/browse/SelectedConversationsActionMenu.java b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
index 7293a36..5ebf7ce 100644
--- a/src/com/android/mail/browse/SelectedConversationsActionMenu.java
+++ b/src/com/android/mail/browse/SelectedConversationsActionMenu.java
@@ -111,6 +111,10 @@
mUpdater = activity.getConversationUpdater();
}
+ public boolean onActionItemClicked(MenuItem item) {
+ return onActionItemClicked(mActionMode, item);
+ }
+
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
boolean handled = true;
@@ -160,6 +164,10 @@
markConversationsRead(false);
} else if (itemId == R.id.star) {
starConversations(true);
+ } else if (itemId == R.id.toggle_read_unread) {
+ if (mActionMode != null) {
+ markConversationsRead(mActionMode.getMenu().findItem(R.id.read).isVisible());
+ }
} else if (itemId == R.id.remove_star) {
if (mFolder.isType(UIProvider.FolderType.STARRED)) {
LogUtils.d(LOG_TAG, "We are in a starred folder, removing the star");
@@ -396,6 +404,7 @@
read.setVisible(!showMarkUnread);
final MenuItem unread = menu.findItem(R.id.unread);
unread.setVisible(showMarkUnread);
+
// We only ever show one of:
// 1) remove folder
// 2) archive
diff --git a/src/com/android/mail/ui/AbstractActivityController.java b/src/com/android/mail/ui/AbstractActivityController.java
index 390afc8..9cf7e56 100644
--- a/src/com/android/mail/ui/AbstractActivityController.java
+++ b/src/com/android/mail/ui/AbstractActivityController.java
@@ -1521,7 +1521,6 @@
final int id = item.getItemId();
LogUtils.d(LOG_TAG, "AbstractController.onOptionsItemSelected(%d) called.", id);
- boolean handled = true;
/** This is NOT a batch action. */
final boolean isBatch = false;
final Collection<Conversation> target = Conversation.listOf(mCurrentConversation);
@@ -1532,95 +1531,121 @@
final UndoCallback undoCallback = getUndoCallbackForDestructiveActionsWithAutoAdvance(
id, mCurrentConversation);
- if (id == R.id.archive) {
- final boolean showDialog = (settings != null && settings.confirmArchive);
- confirmAndDelete(id, target, showDialog, R.plurals.confirm_archive_conversation, undoCallback);
- } else if (id == R.id.remove_folder) {
- delete(R.id.remove_folder, target,
- getDeferredRemoveFolder(target, mFolder, true, isBatch, true, undoCallback),
- isBatch);
- } else if (id == R.id.delete) {
- final boolean showDialog = (settings != null && settings.confirmDelete);
- confirmAndDelete(id, target, showDialog, R.plurals.confirm_delete_conversation, undoCallback);
- } else if (id == R.id.discard_drafts) {
- // drafts are lost forever, so always confirm
- confirmAndDelete(id, target, true /* showDialog */,
- R.plurals.confirm_discard_drafts_conversation, undoCallback);
- } else if (id == R.id.discard_outbox) {
- // discard in outbox means we discard the failed message and save them in drafts
- delete(id, target, getDeferredAction(id, target, isBatch, undoCallback), isBatch);
- } else if (id == R.id.mark_important) {
- updateConversation(Conversation.listOf(mCurrentConversation),
- ConversationColumns.PRIORITY, UIProvider.ConversationPriority.HIGH);
- } else if (id == R.id.mark_not_important) {
- if (mFolder != null && mFolder.isImportantOnly()) {
- delete(R.id.mark_not_important, target,
- getDeferredAction(R.id.mark_not_important, target, isBatch, undoCallback),
+ // Menu items that are targetted, only perform if there actually is a target.
+ boolean handled = false;
+ if (target.size() > 0) {
+ handled = true;
+ if (id == R.id.archive) {
+ final boolean showDialog = (settings != null && settings.confirmArchive);
+ confirmAndDelete(id, target, showDialog, R.plurals.confirm_archive_conversation,
+ undoCallback);
+ } else if (id == R.id.remove_folder) {
+ delete(R.id.remove_folder, target,
+ getDeferredRemoveFolder(target, mFolder, true, isBatch, true, undoCallback),
isBatch);
- } else {
+ } else if (id == R.id.delete) {
+ final boolean showDialog = (settings != null && settings.confirmDelete);
+ confirmAndDelete(id, target, showDialog, R.plurals.confirm_delete_conversation,
+ undoCallback);
+ } else if (id == R.id.discard_drafts) {
+ // drafts are lost forever, so always confirm
+ confirmAndDelete(id, target, true /* showDialog */,
+ R.plurals.confirm_discard_drafts_conversation, undoCallback);
+ } else if (id == R.id.discard_outbox) {
+ // discard in outbox means we discard the failed message and save them in drafts
+ delete(id, target, getDeferredAction(id, target, isBatch, undoCallback), isBatch);
+ } else if (id == R.id.mark_important) {
updateConversation(Conversation.listOf(mCurrentConversation),
- ConversationColumns.PRIORITY, UIProvider.ConversationPriority.LOW);
- }
- } else if (id == R.id.mute) {
- delete(R.id.mute, target, getDeferredAction(R.id.mute, target, isBatch, undoCallback),
- isBatch);
- } else if (id == R.id.report_spam) {
- delete(R.id.report_spam, target,
- getDeferredAction(R.id.report_spam, target, isBatch, undoCallback), isBatch);
- } else if (id == R.id.mark_not_spam) {
- // Currently, since spam messages are only shown in list with
- // other spam messages,
- // marking a message not as spam is a destructive action
- delete(R.id.mark_not_spam, target,
- getDeferredAction(R.id.mark_not_spam, target, isBatch, undoCallback), isBatch);
- } else if (id == R.id.report_phishing) {
- delete(R.id.report_phishing, target,
- getDeferredAction(R.id.report_phishing, target, isBatch, undoCallback), isBatch);
- } else if (id == android.R.id.home) {
- handleUpPress();
- } else if (id == R.id.compose) {
- ComposeActivity.compose(mActivity.getActivityContext(), mAccount);
- } else if (id == R.id.refresh) {
- requestFolderRefresh();
- } else if (id == R.id.settings) {
- Utils.showSettings(mActivity.getActivityContext(), mAccount);
- } else if (id == R.id.help_info_menu_item) {
- mActivity.showHelp(mAccount, mViewMode.getMode());
- } else if (id == R.id.move_to || id == R.id.change_folders) {
- final FolderSelectionDialog dialog = FolderSelectionDialog.getInstance(mAccount,
- Conversation.listOf(mCurrentConversation), isBatch, mFolder,
- id == R.id.move_to);
- if (dialog != null) {
- dialog.show(mActivity.getFragmentManager(), null);
- }
- } else if (id == R.id.move_to_inbox) {
- new AsyncTask<Void, Void, Folder>() {
- @Override
- protected Folder doInBackground(final Void... params) {
- // Get the "move to" inbox
- return Utils.getFolder(mContext, mAccount.settings.moveToInbox,
- true /* allowHidden */);
+ ConversationColumns.PRIORITY, UIProvider.ConversationPriority.HIGH);
+ } else if (id == R.id.mark_not_important) {
+ if (mFolder != null && mFolder.isImportantOnly()) {
+ delete(R.id.mark_not_important, target,
+ getDeferredAction(R.id.mark_not_important, target, isBatch, undoCallback),
+ isBatch);
+ } else {
+ updateConversation(target, ConversationColumns.PRIORITY,
+ UIProvider.ConversationPriority.LOW);
}
+ } else if (id == R.id.mute) {
+ delete(R.id.mute, target, getDeferredAction(R.id.mute, target, isBatch, undoCallback),
+ isBatch);
+ } else if (id == R.id.report_spam) {
+ delete(R.id.report_spam, target,
+ getDeferredAction(R.id.report_spam, target, isBatch, undoCallback),
+ isBatch);
+ } else if (id == R.id.mark_not_spam) {
+ // Currently, since spam messages are only shown in list with
+ // other spam messages,
+ // marking a message not as spam is a destructive action
+ delete(R.id.mark_not_spam, target,
+ getDeferredAction(R.id.mark_not_spam, target, isBatch, undoCallback),
+ isBatch);
+ } else if (id == R.id.report_phishing) {
+ delete(R.id.report_phishing, target,
+ getDeferredAction(R.id.report_phishing, target, isBatch, undoCallback),
+ isBatch);
+ } else if (id == R.id.move_to || id == R.id.change_folders) {
+ final FolderSelectionDialog dialog = FolderSelectionDialog.getInstance(mAccount,
+ target, isBatch, mFolder, id == R.id.move_to);
+ if (dialog != null) {
+ dialog.show(mActivity.getFragmentManager(), null);
+ }
+ } else if (id == R.id.move_to_inbox) {
+ new AsyncTask<Void, Void, Folder>() {
+ @Override
+ protected Folder doInBackground(final Void... params) {
+ // Get the "move to" inbox
+ return Utils.getFolder(mContext, mAccount.settings.moveToInbox,
+ true /* allowHidden */);
+ }
- @Override
- protected void onPostExecute(final Folder moveToInbox) {
- final List<FolderOperation> ops = Lists.newArrayListWithCapacity(1);
- // Add inbox
- ops.add(new FolderOperation(moveToInbox, true));
- assignFolder(ops, Conversation.listOf(mCurrentConversation), true,
- true /* showUndo */, false /* isMoveTo */);
- }
- }.execute((Void[]) null);
- } else if (id == R.id.empty_trash) {
- showEmptyDialog();
- } else if (id == R.id.empty_spam) {
- showEmptyDialog();
- } else if (id == R.id.search) {
- mSearchViewController.showSearchActionBar(
- MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
- } else {
- handled = false;
+ @Override
+ protected void onPostExecute(final Folder moveToInbox) {
+ final List<FolderOperation> ops = Lists.newArrayListWithCapacity(1);
+ // Add inbox
+ ops.add(new FolderOperation(moveToInbox, true));
+ assignFolder(ops, target, true, true /* showUndo */, false /* isMoveTo */);
+ }
+ }.execute((Void[]) null);
+ } else {
+ handled = false;
+ }
}
+
+ // Not handled by the targetted menu items, check the general ones.
+ if (!handled) {
+ handled = true;
+ if (id == android.R.id.home) {
+ handleUpPress();
+ } else if (id == R.id.compose) {
+ ComposeActivity.compose(mActivity.getActivityContext(), mAccount);
+ } else if (id == R.id.refresh) {
+ requestFolderRefresh();
+ } else if (id == R.id.toggle_drawer) {
+ toggleDrawerState();
+ } else if (id == R.id.settings) {
+ Utils.showSettings(mActivity.getActivityContext(), mAccount);
+ } else if (id == R.id.help_info_menu_item) {
+ mActivity.showHelp(mAccount, mViewMode.getMode());
+ } else if (id == R.id.empty_trash) {
+ showEmptyDialog();
+ } else if (id == R.id.empty_spam) {
+ showEmptyDialog();
+ } else if (id == R.id.search) {
+ mSearchViewController.showSearchActionBar(
+ MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
+ } else {
+ handled = false;
+ }
+ }
+
+ // If the controller didn't handle this event, check the CAB menu if it's active.
+ // This is necessary because keyboard shortcuts don't seem to check CAB menus.
+ if (!handled && mCabActionMenu != null && mCabActionMenu.isActivated() &&
+ mCabActionMenu.onActionItemClicked(item)) {
+ handled = true;
+ }
+
return handled;
}
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index bf2e998..471f940 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -327,17 +327,20 @@
return false;
}
- boolean handled = false;
+ boolean handled = true;
final int itemId = item.getItemId();
- if (itemId == R.id.inside_conversation_unread) {
+ if (itemId == R.id.inside_conversation_unread || itemId == R.id.toggle_read_unread) {
markUnread();
- handled = true;
} else if (itemId == R.id.show_original) {
showUntransformedConversation();
- handled = true;
} else if (itemId == R.id.print_all) {
printConversation();
- handled = true;
+ } else if (itemId == R.id.reply) {
+ handleReply();
+ } else if (itemId == R.id.reply_all) {
+ handleReplyAll();
+ } else {
+ handled = false;
}
return handled;
}
@@ -707,6 +710,10 @@
*/
protected abstract void printConversation();
+ // These methods should perform default reply/replyall action on the last message.
+ protected abstract void handleReply();
+ protected abstract void handleReplyAll();
+
public boolean shouldAlwaysShowImages() {
return (mAccount != null) && (mAccount.settings.showImages == Settings.ShowImages.ALWAYS);
}
diff --git a/src/com/android/mail/ui/ActionBarController.java b/src/com/android/mail/ui/ActionBarController.java
index a9dc371..056de30 100644
--- a/src/com/android/mail/ui/ActionBarController.java
+++ b/src/com/android/mail/ui/ActionBarController.java
@@ -274,13 +274,10 @@
setConversationModeOptions(menu);
break;
case ViewMode.CONVERSATION_LIST:
+ case ViewMode.SEARCH_RESULTS_LIST:
// The search menu item should only be visible for non-tablet devices
Utils.setMenuItemVisibility(menu, R.id.search,
mAccount.supportsSearch() && !mIsOnTablet);
- case ViewMode.SEARCH_RESULTS_LIST:
- // Hide compose and search
- Utils.setMenuItemVisibility(menu, R.id.compose, false);
- break;
}
return false;
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index c53264b..25c1310 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -73,6 +73,7 @@
import com.android.mail.browse.ScrollIndicatorsView;
import com.android.mail.browse.SuperCollapsedBlock;
import com.android.mail.browse.WebViewContextMenu;
+import com.android.mail.compose.ComposeActivity;
import com.android.mail.content.ObjectCursor;
import com.android.mail.print.PrintUtils;
import com.android.mail.providers.Account;
@@ -841,12 +842,15 @@
}
private MessageHeaderItem getLastMessageHeaderItem() {
- final int count = mAdapter.getCount();
- if (count < 3) {
- LogUtils.wtf(LOG_TAG, "not enough items in the adapter. count: %s", count);
- return null;
+ int pos = mAdapter.getCount();
+ while (--pos >= 0) {
+ final ConversationOverlayItem item = mAdapter.getItem(pos);
+ if (item instanceof MessageHeaderItem) {
+ return (MessageHeaderItem) item;
+ }
}
- return (MessageHeaderItem) mAdapter.getItem(count - 2);
+ LogUtils.wtf(LOG_TAG, "No message header found");
+ return null;
}
private void renderSuperCollapsedBlock(int start, int end, boolean hasDraft) {
@@ -1806,4 +1810,26 @@
PrintUtils.printConversation(mActivity.getActivityContext(), getMessageCursor(),
mAddressCache, mConversation.getBaseUri(mBaseUri), true /* useJavascript */);
}
+
+ @Override
+ protected void handleReply() {
+ final MessageHeaderItem item = getLastMessageHeaderItem();
+ if (item != null) {
+ final ConversationMessage msg = item.getMessage();
+ if (msg != null) {
+ ComposeActivity.reply(getActivity(), mAccount, msg);
+ }
+ }
+ }
+
+ @Override
+ protected void handleReplyAll() {
+ final MessageHeaderItem item = getLastMessageHeaderItem();
+ if (item != null) {
+ final ConversationMessage msg = item.getMessage();
+ if (msg != null) {
+ ComposeActivity.replyAll(getActivity(), mAccount, msg);
+ }
+ }
+ }
}
diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java
index 7c4a9d9..7c80380 100644
--- a/src/com/android/mail/ui/SecureConversationViewFragment.java
+++ b/src/com/android/mail/ui/SecureConversationViewFragment.java
@@ -33,6 +33,7 @@
import com.android.mail.browse.ConversationViewHeader;
import com.android.mail.browse.MessageCursor;
import com.android.mail.browse.MessageHeaderView;
+import com.android.mail.compose.ComposeActivity;
import com.android.mail.content.ObjectCursor;
import com.android.mail.providers.Account;
import com.android.mail.providers.Conversation;
@@ -290,4 +291,20 @@
protected void printConversation() {
mViewController.printMessage();
}
+
+ @Override
+ protected void handleReply() {
+ final ConversationMessage msg = mViewController.getMessage();
+ if (msg != null) {
+ ComposeActivity.reply(getActivity(), mAccount, msg);
+ }
+ }
+
+ @Override
+ protected void handleReplyAll() {
+ final ConversationMessage msg = mViewController.getMessage();
+ if (msg != null) {
+ ComposeActivity.replyAll(getActivity(), mAccount, msg);
+ }
+ }
}
diff --git a/src/com/android/mail/utils/Utils.java b/src/com/android/mail/utils/Utils.java
index b3bdd7e..4d9b63f 100644
--- a/src/com/android/mail/utils/Utils.java
+++ b/src/com/android/mail/utils/Utils.java
@@ -789,6 +789,7 @@
return;
}
item.setVisible(shouldShow);
+ item.setEnabled(shouldShow);
}
/**