Remove phone activities and implement one-pane
The primary purpose of this CL is to remove phone activities, so the one pane implementation is very much temporary and primitive, but it should offer minimal operations. Change-Id: If57f81db7c605c95664d49044a5cc082beda59c0
Before Width: | Height: | Size: 443 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 916 B |
Before Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 381 B |
Before Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 331 B |
Before Width: | Height: | Size: 723 B |
Before Width: | Height: | Size: 797 B |
Before Width: | Height: | Size: 634 B |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 310 B |
Before Width: | Height: | Size: 674 B |
Before Width: | Height: | Size: 728 B |
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical" >
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/account_folder_list_fragment"
|
|
||||||
class="com.android.email.activity.AccountFolderListFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
|
@ -1,102 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 The Android Open Source Project
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<com.android.email.activity.AccountFolderListItem
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingRight="4dip">
|
|
||||||
<View
|
|
||||||
android:id="@+id/chip"
|
|
||||||
android:background="@drawable/appointment_indicator_leftside_1"
|
|
||||||
android:layout_width="4dip"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_centerVertical="true" />
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/folder_icon"
|
|
||||||
android:layout_width="30dip"
|
|
||||||
android:layout_height="30dip"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_marginLeft="4dip"
|
|
||||||
android:layout_marginRight="4dip"
|
|
||||||
android:minWidth="30dip"
|
|
||||||
android:src="@drawable/ic_list_folder" />
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_weight="1">
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/subject"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="8dip"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/name"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/status"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
|
||||||
android:textColor="?android:attr/textColorTertiary"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content" />
|
|
||||||
</LinearLayout>
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/new_message_count"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="4dip"
|
|
||||||
android:background="@drawable/ind_unread"
|
|
||||||
style="@style/unreadCount"/>
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/all_message_count"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="4dip"
|
|
||||||
android:background="@drawable/ind_sum"
|
|
||||||
style="@style/unreadCount"/>
|
|
||||||
</LinearLayout>
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/default_sender"
|
|
||||||
android:layout_width="12dip"
|
|
||||||
android:layout_height="12dip"
|
|
||||||
android:minWidth="12dip"
|
|
||||||
android:layout_margin="5dip"
|
|
||||||
android:src="@drawable/ind_default"/>
|
|
||||||
<View
|
|
||||||
android:id="@+id/folder_separator"
|
|
||||||
android:background="@color/account_folder_list_item_separator"
|
|
||||||
android:layout_width="1dip"
|
|
||||||
android:layout_height="40dip"
|
|
||||||
android:layout_marginLeft="5dip" />
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/folder_button"
|
|
||||||
android:layout_width="40dip"
|
|
||||||
android:layout_height="40dip"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:minWidth="30dip"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingLeft="5dip"
|
|
||||||
android:src="@drawable/btn_folder"/>
|
|
||||||
</com.android.email.activity.AccountFolderListItem>
|
|
|
@ -35,10 +35,16 @@
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:background="#ffff66"
|
android:background="#ffff66"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fragment_placeholder"
|
android:id="@+id/fragment_placeholder"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dip"
|
||||||
|
android:layout_weight="1"
|
||||||
|
/>
|
||||||
|
<!-- TODO temporarily gone -->
|
||||||
|
<include
|
||||||
|
layout="@layout/message_command_button_view"
|
||||||
|
android:id="@+id/message_command_buttons"
|
||||||
|
android:visibility="gone"
|
||||||
/>
|
/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<include layout="@layout/connection_error_banner" />
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/mailbox_list_fragment"
|
|
||||||
class="com.android.email.activity.MailboxListFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<include layout="@layout/connection_error_banner" />
|
|
||||||
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/message_list_fragment"
|
|
||||||
class="com.android.email.activity.MessageListFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
|
@ -1,53 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2008 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@android:color/white">
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/message_view_fragment"
|
|
||||||
class="com.android.email.activity.MessageViewFragment"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dip"
|
|
||||||
android:layout_weight="1"
|
|
||||||
/>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/button_panel"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="5dip"
|
|
||||||
android:paddingLeft="4dip"
|
|
||||||
android:paddingRight="4dip"
|
|
||||||
android:paddingBottom="1dip"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/moveToNewer"
|
|
||||||
android:text="@string/message_view_move_to_newer"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_width="0dip"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
<Button
|
|
||||||
android:id="@+id/moveToOlder"
|
|
||||||
android:text="@string/message_view_move_to_older"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_width="0dip"
|
|
||||||
android:layout_weight="1" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2008 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- xlarge -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/send"
|
|
||||||
android:title="@string/send_action"
|
|
||||||
android:showAsAction="always|withText"
|
|
||||||
android:icon="@drawable/ic_menu_send_holo_light"
|
|
||||||
android:alphabeticShortcut="s"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/save"
|
|
||||||
android:title="@string/save_draft_action"
|
|
||||||
android:showAsAction="always"
|
|
||||||
android:alphabeticShortcut="d"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/discard"
|
|
||||||
android:title="@string/discard_action"
|
|
||||||
android:showAsAction="always"
|
|
||||||
android:icon="@drawable/ic_menu_trash_holo_light"
|
|
||||||
android:alphabeticShortcut="q"
|
|
||||||
/>
|
|
||||||
</menu>
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open_folder"
|
|
||||||
android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/compose"
|
|
||||||
android:title="@string/compose_action" />
|
|
||||||
<item android:id="@+id/refresh_account"
|
|
||||||
android:title="@string/refresh_action" />
|
|
||||||
<item android:id="@+id/edit_account"
|
|
||||||
android:title="@string/account_settings_action" />
|
|
||||||
<item android:id="@+id/delete_account"
|
|
||||||
android:title="@string/remove_account_action" />
|
|
||||||
</menu>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2008 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/compose"
|
|
||||||
android:alphabeticShortcut="c"
|
|
||||||
android:title="@string/compose_action"
|
|
||||||
android:icon="@drawable/ic_menu_compose"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/check_mail"
|
|
||||||
android:alphabeticShortcut="r"
|
|
||||||
android:title="@string/refresh_action"
|
|
||||||
android:icon="@drawable/ic_menu_refresh"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/add_new_account"
|
|
||||||
android:title="@string/add_account_action"
|
|
||||||
android:icon="@android:drawable/ic_menu_add"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/account_settings"
|
|
||||||
android:title="@string/account_settings_action"
|
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<!--
|
|
||||||
<item android:id="@+id/search"
|
|
||||||
android:title="@string/search_action" />
|
|
||||||
<item android:id="@+id/preferences"
|
|
||||||
android:title="@string/preferences_action" />
|
|
||||||
-->
|
|
||||||
</menu>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2008 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open_folder"
|
|
||||||
android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/check_mail"
|
|
||||||
android:title="@string/refresh_action" />
|
|
||||||
</menu>
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/compose"
|
|
||||||
android:alphabeticShortcut="c"
|
|
||||||
android:title="@string/compose_action"
|
|
||||||
android:icon="@drawable/ic_menu_compose"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/refresh"
|
|
||||||
android:alphabeticShortcut="r"
|
|
||||||
android:title="@string/refresh_action"
|
|
||||||
android:icon="@drawable/ic_menu_refresh"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/account_settings"
|
|
||||||
android:title="@string/account_settings_action"
|
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
|
||||||
/>
|
|
||||||
</menu>
|
|
|
@ -14,8 +14,6 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- small -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item
|
<item
|
||||||
android:id="@+id/send"
|
android:id="@+id/send"
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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 context menu is shown for message lists except in trash, outbox, or drafts -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open" android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/delete" android:title="@string/delete_action" />
|
|
||||||
<item android:id="@+id/forward" android:title="@string/forward_action" />
|
|
||||||
<item android:id="@+id/reply_all" android:title="@string/reply_all_action" />
|
|
||||||
<item android:id="@+id/reply" android:title="@string/reply_action" />
|
|
||||||
<item android:id="@+id/mark_as_read" android:title="@string/mark_as_read_action" />
|
|
||||||
</menu>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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 context menu is shown for drafts message lists -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open" android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/delete" android:title="@string/discard_action" />
|
|
||||||
</menu>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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 context menu is shown for outbox message lists -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open" android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/delete" android:title="@string/discard_action" />
|
|
||||||
</menu>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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 context menu is shown for trash message lists -->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/open" android:title="@string/open_action" />
|
|
||||||
<item android:id="@+id/delete" android:title="@string/delete_action" />
|
|
||||||
</menu>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2009 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/refresh"
|
|
||||||
android:alphabeticShortcut="r"
|
|
||||||
android:title="@string/refresh_action"
|
|
||||||
android:icon="@drawable/ic_menu_refresh_holo_light"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/compose"
|
|
||||||
android:alphabeticShortcut="c"
|
|
||||||
android:title="@string/compose_action"
|
|
||||||
android:icon="@drawable/ic_menu_compose_holo_light"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/folders"
|
|
||||||
android:title="@string/folders_action"
|
|
||||||
android:icon="@drawable/ic_menu_folder"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/accounts"
|
|
||||||
android:title="@string/accounts_action"
|
|
||||||
android:icon="@drawable/ic_menu_account_list"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
<item android:id="@+id/account_settings"
|
|
||||||
android:title="@string/account_settings_action"
|
|
||||||
android:icon="@android:drawable/ic_menu_preferences"
|
|
||||||
android:showAsAction="ifRoom"
|
|
||||||
/>
|
|
||||||
</menu>
|
|
|
@ -1,48 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Copyright (C) 2008 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.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/delete"
|
|
||||||
android:alphabeticShortcut="q"
|
|
||||||
android:title="@string/delete_action"
|
|
||||||
android:icon="@android:drawable/ic_menu_delete"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/forward"
|
|
||||||
android:alphabeticShortcut="f"
|
|
||||||
android:title="@string/forward_action"
|
|
||||||
android:icon="@drawable/ic_menu_forward_mail"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/reply"
|
|
||||||
android:alphabeticShortcut="r"
|
|
||||||
android:title="@string/reply_action"
|
|
||||||
android:icon="@drawable/ic_menu_reply"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/reply_all"
|
|
||||||
android:alphabeticShortcut="a"
|
|
||||||
android:title="@string/reply_all_action"
|
|
||||||
android:icon="@drawable/ic_menu_reply_all"
|
|
||||||
/>
|
|
||||||
<item
|
|
||||||
android:id="@+id/mark_as_unread"
|
|
||||||
android:alphabeticShortcut="u"
|
|
||||||
android:title="@string/mark_as_unread_action"
|
|
||||||
android:icon="@drawable/ic_menu_mark_unread_holo_light"
|
|
||||||
/>
|
|
||||||
</menu>
|
|
|
@ -1,313 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.Controller;
|
|
||||||
import com.android.email.ControllerResultUiThreadWrapper;
|
|
||||||
import com.android.email.Email;
|
|
||||||
import com.android.email.NotificationController;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.email.activity.setup.AccountSettingsXL;
|
|
||||||
import com.android.email.activity.setup.AccountSetupBasics;
|
|
||||||
import com.android.emailcommon.mail.MessagingException;
|
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.app.Dialog;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
public class AccountFolderList extends Activity implements AccountFolderListFragment.Callback {
|
|
||||||
private static final int DIALOG_REMOVE_ACCOUNT = 1;
|
|
||||||
|
|
||||||
private static final String ICICLE_SELECTED_ACCOUNT = "com.android.email.selectedAccount";
|
|
||||||
private EmailContent.Account mSelectedContextAccount;
|
|
||||||
|
|
||||||
// UI Support
|
|
||||||
private AccountFolderListFragment mListFragment;
|
|
||||||
|
|
||||||
private Controller.Result mControllerCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the Accounts list activity. Uses the CLEAR_TOP flag which means that other stacked
|
|
||||||
* activities may be killed in order to get back to Accounts.
|
|
||||||
*/
|
|
||||||
public static void actionShowAccounts(Context context) {
|
|
||||||
Intent i = new Intent(context, AccountFolderList.class);
|
|
||||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
context.startActivity(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle icicle) {
|
|
||||||
super.onCreate(icicle);
|
|
||||||
ActivityHelper.debugSetWindowFlags(this);
|
|
||||||
|
|
||||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
|
||||||
setContentView(R.layout.account_folder_list);
|
|
||||||
|
|
||||||
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
|
|
||||||
new Handler(), new ControllerResults());
|
|
||||||
mListFragment =
|
|
||||||
(AccountFolderListFragment) getFragmentManager()
|
|
||||||
.findFragmentById(R.id.account_folder_list_fragment);
|
|
||||||
mListFragment.bindActivityInfo(this);
|
|
||||||
|
|
||||||
if (icicle != null && icicle.containsKey(ICICLE_SELECTED_ACCOUNT)) {
|
|
||||||
mSelectedContextAccount = (Account) icicle.getParcelable(ICICLE_SELECTED_ACCOUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Halt the progress indicator (we'll display it later when needed)
|
|
||||||
setProgressBarIndeterminate(true);
|
|
||||||
setProgressBarIndeterminateVisibility(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
if (mSelectedContextAccount != null) {
|
|
||||||
outState.putParcelable(ICICLE_SELECTED_ACCOUNT, mSelectedContextAccount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
Controller.getInstance(getApplication()).removeResultCallback(mControllerCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
NotificationManager notifMgr = (NotificationManager)
|
|
||||||
getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
notifMgr.cancel(1);
|
|
||||||
|
|
||||||
Controller.getInstance(getApplication()).addResultCallback(mControllerCallback);
|
|
||||||
|
|
||||||
// Exit immediately if the accounts list has changed (e.g. externally deleted)
|
|
||||||
if (Email.getNotifyUiAccountsChanged()) {
|
|
||||||
Welcome.actionStart(this);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onAddNewAccount() {
|
|
||||||
AccountSetupBasics.actionNewAccount(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onEditAccount(long accountId) {
|
|
||||||
AccountSettingsXL.actionSettings(this, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onRefresh(long accountId) {
|
|
||||||
if (accountId == -1) {
|
|
||||||
// TODO implement a suitable "Refresh all accounts" / "check mail" comment in Controller
|
|
||||||
// TODO this is temp
|
|
||||||
Toast.makeText(this, getString(R.string.account_folder_list_refresh_toast),
|
|
||||||
Toast.LENGTH_LONG).show();
|
|
||||||
} else {
|
|
||||||
showProgressIcon(true);
|
|
||||||
Controller.getInstance(getApplication()).updateMailboxList(accountId);
|
|
||||||
// TODO update the inbox too
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onCompose(long accountId) {
|
|
||||||
if (accountId == -1) {
|
|
||||||
accountId = Account.getDefaultAccountId(this);
|
|
||||||
}
|
|
||||||
if (accountId != -1) {
|
|
||||||
MessageCompose.actionCompose(this, accountId);
|
|
||||||
} else {
|
|
||||||
onAddNewAccount();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onDeleteAccount(long accountId) {
|
|
||||||
mSelectedContextAccount = Account.restoreAccountWithId(this, accountId);
|
|
||||||
showDialog(DIALOG_REMOVE_ACCOUNT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onOpenAccount(long accountId) {
|
|
||||||
MessageList.actionHandleAccount(this, accountId, Mailbox.TYPE_INBOX);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onOpenMailbox(long mailboxId) {
|
|
||||||
MessageList.actionHandleMailbox(this, mailboxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountFolderListFragment.Callback */
|
|
||||||
public void onOpenMailboxes(long accountId) {
|
|
||||||
MailboxList.actionHandleAccount(this, accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Dialog onCreateDialog(int id, Bundle args) {
|
|
||||||
switch (id) {
|
|
||||||
case DIALOG_REMOVE_ACCOUNT:
|
|
||||||
return createRemoveAccountDialog();
|
|
||||||
}
|
|
||||||
return super.onCreateDialog(id, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dialog createRemoveAccountDialog() {
|
|
||||||
final Activity activity = this;
|
|
||||||
return new AlertDialog.Builder(this)
|
|
||||||
.setIconAttribute(android.R.attr.alertDialogIcon)
|
|
||||||
.setTitle(R.string.account_delete_dlg_title)
|
|
||||||
.setMessage(getString(R.string.account_delete_dlg_instructions_fmt,
|
|
||||||
mSelectedContextAccount.getDisplayName()))
|
|
||||||
.setPositiveButton(R.string.okay_action, new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
|
||||||
final long accountId = mSelectedContextAccount.mId;
|
|
||||||
dismissDialog(DIALOG_REMOVE_ACCOUNT);
|
|
||||||
// TODO Do this automatically in the NotificationController as part of a
|
|
||||||
// ContentObserver
|
|
||||||
// Dismiss new message notification.
|
|
||||||
NotificationController.getInstance(activity)
|
|
||||||
.cancelNewMessageNotification(accountId);
|
|
||||||
int numAccounts = EmailContent.count(activity,
|
|
||||||
Account.CONTENT_URI, null, null);
|
|
||||||
mListFragment.hideDeletingAccount(mSelectedContextAccount.mId);
|
|
||||||
|
|
||||||
Controller.getInstance(activity).deleteAccount(accountId);
|
|
||||||
if (numAccounts == 1) {
|
|
||||||
AccountSetupBasics.actionNewAccount(activity);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
|
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
|
||||||
dismissDialog(DIALOG_REMOVE_ACCOUNT);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a cached dialog with current values (e.g. account name)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onPrepareDialog(int id, Dialog dialog, Bundle args) {
|
|
||||||
switch (id) {
|
|
||||||
case DIALOG_REMOVE_ACCOUNT:
|
|
||||||
AlertDialog alert = (AlertDialog) dialog;
|
|
||||||
alert.setMessage(getString(R.string.account_delete_dlg_instructions_fmt,
|
|
||||||
mSelectedContextAccount.getDisplayName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.add_new_account:
|
|
||||||
onAddNewAccount();
|
|
||||||
break;
|
|
||||||
case R.id.check_mail:
|
|
||||||
onRefresh(-1);
|
|
||||||
break;
|
|
||||||
case R.id.compose:
|
|
||||||
onCompose(-1);
|
|
||||||
break;
|
|
||||||
case R.id.account_settings:
|
|
||||||
onEditAccount(-1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
super.onCreateOptionsMenu(menu);
|
|
||||||
getMenuInflater().inflate(R.menu.account_folder_list_option, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showProgressIcon(boolean show) {
|
|
||||||
setProgressBarIndeterminateVisibility(show);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper},
|
|
||||||
* so all methods are called on the UI thread.
|
|
||||||
*/
|
|
||||||
private class ControllerResults extends Controller.Result {
|
|
||||||
@Override
|
|
||||||
public void updateMailboxListCallback(MessagingException result, long accountKey,
|
|
||||||
int progress) {
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
|
||||||
long mailboxKey, int progress, int numNewMessages,
|
|
||||||
ArrayList<Long> addedMessages) {
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serviceCheckMailCallback(MessagingException result, long accountId,
|
|
||||||
long mailboxId, int progress, long tag) {
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMailCallback(MessagingException result, long accountId, long messageId,
|
|
||||||
int progress) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgress(MessagingException result, int progress) {
|
|
||||||
showProgressIcon(result == null && progress < 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,474 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.Controller;
|
|
||||||
import com.android.email.ControllerResultUiThreadWrapper;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.emailcommon.mail.MessagingException;
|
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Message;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.MessageColumns;
|
|
||||||
import com.android.emailcommon.utility.Utility;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ListFragment;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.MatrixCursor;
|
|
||||||
import android.database.MatrixCursor.RowBuilder;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.ContextMenu;
|
|
||||||
import android.view.ContextMenu.ContextMenuInfo;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.AdapterView;
|
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ListAdapter;
|
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
public class AccountFolderListFragment extends ListFragment
|
|
||||||
implements OnItemClickListener, AccountsAdapter.Callback {
|
|
||||||
|
|
||||||
// UI Support
|
|
||||||
private Activity mActivity;
|
|
||||||
private ListView mListView;
|
|
||||||
private Callback mCallback;
|
|
||||||
|
|
||||||
// Tasks and Data
|
|
||||||
private AccountsAdapter mListAdapter;
|
|
||||||
private LoadAccountsTask mLoadAccountsTask;
|
|
||||||
private Controller.Result mControllerCallback;
|
|
||||||
|
|
||||||
private static final String FAVORITE_COUNT_SELECTION =
|
|
||||||
MessageColumns.FLAG_FAVORITE + "= 1";
|
|
||||||
private static final String MAILBOX_TYPE_SELECTION =
|
|
||||||
MailboxColumns.TYPE + " =?";
|
|
||||||
private static final String MAILBOX_ID_SELECTION =
|
|
||||||
MessageColumns.MAILBOX_KEY + " =?";
|
|
||||||
private static final String[] MAILBOX_SUM_OF_UNREAD_COUNT_PROJECTION = new String [] {
|
|
||||||
"sum(" + MailboxColumns.UNREAD_COUNT + ")"
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface that owning activities must implement
|
|
||||||
*/
|
|
||||||
public interface Callback {
|
|
||||||
/** Called when the user clicks on a specific account */
|
|
||||||
public void onOpenAccount(long accountId);
|
|
||||||
/** Called when the user clicks on a specific (currently, only magic mailbox) */
|
|
||||||
public void onOpenMailbox(long mailboxId);
|
|
||||||
/** Called when the user clicks to open the mailbox list for a specific account */
|
|
||||||
public void onOpenMailboxes(long accountId);
|
|
||||||
/** Begin composing a message in a specific account, or -1 for the default account */
|
|
||||||
public void onCompose(long accountId);
|
|
||||||
/** Begin refreshing a specific account, or -1 for all accounts */
|
|
||||||
public void onRefresh(long accountId);
|
|
||||||
/** Begin edit settings for a specific account */
|
|
||||||
public void onEditAccount(long accountId);
|
|
||||||
/** Delete a specific account */
|
|
||||||
public void onDeleteAccount(long accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to do initial creation of a fragment. This is called after
|
|
||||||
* {@link #onAttach(Activity)} and before {@link #onActivityCreated(Bundle)}.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by activity during onCreate() to bind additional information
|
|
||||||
* @param callback if non-null, UI clicks (e.g. refresh or open) will be delivered here
|
|
||||||
*/
|
|
||||||
public void bindActivityInfo(Callback callback) {
|
|
||||||
mCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the fragment is instantiated, but not yet displayed.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onActivityCreated(Bundle savedInstanceState) {
|
|
||||||
super.onActivityCreated(savedInstanceState);
|
|
||||||
mActivity = getActivity();
|
|
||||||
|
|
||||||
mListView = getListView();
|
|
||||||
mListView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_INSET);
|
|
||||||
mListView.setOnItemClickListener(this);
|
|
||||||
mListView.setLongClickable(true);
|
|
||||||
registerForContextMenu(mListView);
|
|
||||||
|
|
||||||
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
|
|
||||||
new Handler(), new ControllerResults());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the Fragment is visible to the user.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onStart() {
|
|
||||||
super.onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the fragment is visible to the user and actively running.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
Controller.getInstance(mActivity).addResultCallback(mControllerCallback);
|
|
||||||
updateAccounts();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the fragment is no longer displayed
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
Controller.getInstance(mActivity).removeResultCallback(mControllerCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the Fragment is no longer started.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
Utility.cancelTaskInterrupt(mLoadAccountsTask);
|
|
||||||
mLoadAccountsTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the fragment is no longer in use.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
if (mListAdapter != null) {
|
|
||||||
mListAdapter.changeCursor(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo info) {
|
|
||||||
super.onCreateContextMenu(menu, v, info);
|
|
||||||
AdapterView.AdapterContextMenuInfo menuInfo = (AdapterView.AdapterContextMenuInfo) info;
|
|
||||||
if (mListAdapter.isMailbox(menuInfo.position)) {
|
|
||||||
Cursor c = (Cursor) mListView.getItemAtPosition(menuInfo.position);
|
|
||||||
String displayName = c.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
|
|
||||||
menu.setHeaderTitle(displayName);
|
|
||||||
mActivity.getMenuInflater()
|
|
||||||
.inflate(R.menu.account_folder_list_smart_folder_context, menu);
|
|
||||||
} else if (mListAdapter.isAccount(menuInfo.position)) {
|
|
||||||
Cursor c = (Cursor) mListView.getItemAtPosition(menuInfo.position);
|
|
||||||
String accountName = c.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
|
|
||||||
menu.setHeaderTitle(accountName);
|
|
||||||
mActivity.getMenuInflater().inflate(R.menu.account_folder_list_context, menu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onContextItemSelected(MenuItem item) {
|
|
||||||
AdapterView.AdapterContextMenuInfo menuInfo =
|
|
||||||
(AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
|
|
||||||
|
|
||||||
// Drop the event if there's nowhere to send it (it's probably late-arriving)
|
|
||||||
if (mCallback == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mListAdapter.isMailbox(menuInfo.position)) {
|
|
||||||
Cursor c = (Cursor) mListView.getItemAtPosition(menuInfo.position);
|
|
||||||
long id = c.getLong(AccountsAdapter.MAILBOX_COLUMN_ID);
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.open_folder:
|
|
||||||
mCallback.onOpenMailbox(id);
|
|
||||||
break;
|
|
||||||
case R.id.check_mail:
|
|
||||||
mCallback.onRefresh(-1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if (mListAdapter.isAccount(menuInfo.position)) {
|
|
||||||
Cursor c = (Cursor) mListView.getItemAtPosition(menuInfo.position);
|
|
||||||
long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.open_folder:
|
|
||||||
mCallback.onOpenAccount(accountId);
|
|
||||||
break;
|
|
||||||
case R.id.compose:
|
|
||||||
mCallback.onCompose(accountId);
|
|
||||||
break;
|
|
||||||
case R.id.refresh_account:
|
|
||||||
mCallback.onRefresh(accountId);
|
|
||||||
break;
|
|
||||||
case R.id.edit_account:
|
|
||||||
mCallback.onEditAccount(accountId);
|
|
||||||
break;
|
|
||||||
case R.id.delete_account:
|
|
||||||
mCallback.onDeleteAccount(accountId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements OnItemClickListener.onItemClick */
|
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
|
||||||
// Drop the event if there's nowhere to send it (it's probably late-arriving)
|
|
||||||
if (mCallback == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mListAdapter.isMailbox(position)) {
|
|
||||||
mCallback.onOpenMailbox(id);
|
|
||||||
} else if (mListAdapter.isAccount(position)) {
|
|
||||||
mCallback.onOpenAccount(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Implements AccountsAdapter.Controller */
|
|
||||||
public void onClickAccountFolders(long accountId) {
|
|
||||||
if (mCallback != null) {
|
|
||||||
mCallback.onOpenMailboxes(accountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trigger accounts list reload
|
|
||||||
*/
|
|
||||||
private void updateAccounts() {
|
|
||||||
Utility.cancelTaskInterrupt(mLoadAccountsTask);
|
|
||||||
mLoadAccountsTask = (LoadAccountsTask) new LoadAccountsTask().execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by container to mark an account as "being deleted" (we quickly hide it)
|
|
||||||
*/
|
|
||||||
public void hideDeletingAccount(long accountId) {
|
|
||||||
mListAdapter.addOnDeletingAccount(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getUnreadCountByMailboxType(Context context, int type) {
|
|
||||||
int count = 0;
|
|
||||||
Cursor c = context.getContentResolver().query(Mailbox.CONTENT_URI,
|
|
||||||
MAILBOX_SUM_OF_UNREAD_COUNT_PROJECTION,
|
|
||||||
MAILBOX_TYPE_SELECTION,
|
|
||||||
new String[] { String.valueOf(type) }, null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
return c.getInt(0);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int getCountByMailboxType(Context context, int type) {
|
|
||||||
int count = 0;
|
|
||||||
Cursor c = context.getContentResolver().query(Mailbox.CONTENT_URI,
|
|
||||||
EmailContent.ID_PROJECTION, MAILBOX_TYPE_SELECTION,
|
|
||||||
new String[] { String.valueOf(type) }, null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
c.moveToPosition(-1);
|
|
||||||
while (c.moveToNext()) {
|
|
||||||
count += EmailContent.count(context, Message.CONTENT_URI,
|
|
||||||
MAILBOX_ID_SELECTION,
|
|
||||||
new String[] {
|
|
||||||
String.valueOf(c.getLong(EmailContent.ID_PROJECTION_COLUMN)) });
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the group and child cursors that support the summary views (aka "at a glance").
|
|
||||||
*
|
|
||||||
* This is a placeholder implementation with significant problems that need to be addressed:
|
|
||||||
*
|
|
||||||
* TODO: We should only show summary mailboxes if they are non-empty. So there needs to be
|
|
||||||
* a more dynamic child-cursor here, probably listening for update notifications on a number
|
|
||||||
* of other internally-held queries such as count-of-inbox, count-of-unread, etc.
|
|
||||||
*
|
|
||||||
* TODO: This simple list is incomplete. For example, we probably want drafts, outbox, and
|
|
||||||
* (maybe) sent (again, these would be displayed only when non-empty).
|
|
||||||
*
|
|
||||||
* TODO: We need a way to count total unread in all inboxes (probably with some provider help)
|
|
||||||
*
|
|
||||||
* TODO: We need a way to count total # messages in all other summary boxes (probably with
|
|
||||||
* some provider help).
|
|
||||||
*
|
|
||||||
* TODO use narrower account projection (see LoadAccountsTask)
|
|
||||||
*/
|
|
||||||
private MatrixCursor getSummaryChildCursor() {
|
|
||||||
MatrixCursor childCursor = new MatrixCursor(AccountsAdapter.MAILBOX_PROJECTION);
|
|
||||||
int count;
|
|
||||||
RowBuilder row;
|
|
||||||
// TYPE_INBOX
|
|
||||||
count = getUnreadCountByMailboxType(mActivity, Mailbox.TYPE_INBOX);
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_INBOXES)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
// MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(mActivity.getString(R.string.account_folder_list_summary_inbox));
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_INBOX)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
// TYPE_MAIL (FAVORITES)
|
|
||||||
count = EmailContent.count(mActivity, Message.CONTENT_URI, FAVORITE_COUNT_SELECTION, null);
|
|
||||||
if (count > 0) {
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_FAVORITES)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
// MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(mActivity.getString(R.string.account_folder_list_summary_starred));
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_MAIL)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
}
|
|
||||||
// TYPE_DRAFTS
|
|
||||||
count = getCountByMailboxType(mActivity, Mailbox.TYPE_DRAFTS);
|
|
||||||
if (count > 0) {
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_DRAFTS)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
// MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(mActivity.getString(R.string.account_folder_list_summary_drafts));
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_DRAFTS)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
}
|
|
||||||
// TYPE_OUTBOX
|
|
||||||
count = getCountByMailboxType(mActivity, Mailbox.TYPE_OUTBOX);
|
|
||||||
if (count > 0) {
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_OUTBOX)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
// MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(mActivity.getString(R.string.account_folder_list_summary_outbox));
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_OUTBOX)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
}
|
|
||||||
return childCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Async task to handle the accounts query outside of the UI thread
|
|
||||||
*/
|
|
||||||
private class LoadAccountsTask extends AsyncTask<Void, Void, Object[]> {
|
|
||||||
@Override
|
|
||||||
protected Object[] doInBackground(Void... params) {
|
|
||||||
// Create the summaries cursor
|
|
||||||
Cursor c1 = null;
|
|
||||||
Cursor c2 = null;
|
|
||||||
Long defaultAccount = null;
|
|
||||||
if (!isCancelled()) {
|
|
||||||
// Create the summaries cursor
|
|
||||||
c1 = getSummaryChildCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isCancelled()) {
|
|
||||||
// TODO use a custom projection and don't have to sample all of these columns
|
|
||||||
c2 = mActivity.getContentResolver().query(
|
|
||||||
EmailContent.Account.CONTENT_URI,
|
|
||||||
EmailContent.Account.CONTENT_PROJECTION, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isCancelled()) {
|
|
||||||
defaultAccount = Account.getDefaultAccountId(mActivity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCancelled()) {
|
|
||||||
if (c1 != null) c1.close();
|
|
||||||
if (c2 != null) c2.close();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new Object[] { c1, c2 , defaultAccount};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Object[] params) {
|
|
||||||
if (isCancelled() || params == null) {
|
|
||||||
if (params != null) {
|
|
||||||
Cursor c1 = (Cursor)params[0];
|
|
||||||
if (c1 != null) {
|
|
||||||
c1.close();
|
|
||||||
}
|
|
||||||
Cursor c2 = (Cursor)params[1];
|
|
||||||
if (c2 != null) {
|
|
||||||
c2.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Before writing a new list adapter into the listview, we need to
|
|
||||||
// shut down the old one (if any).
|
|
||||||
ListAdapter oldAdapter = mListView.getAdapter();
|
|
||||||
if (oldAdapter != null && oldAdapter instanceof CursorAdapter) {
|
|
||||||
((CursorAdapter)oldAdapter).changeCursor(null);
|
|
||||||
}
|
|
||||||
// Now create a new list adapter and install it
|
|
||||||
mListAdapter = AccountsAdapter.getInstance((Cursor)params[0], (Cursor)params[1],
|
|
||||||
mActivity, (Long)params[2], AccountFolderListFragment.this);
|
|
||||||
setListAdapter(mListAdapter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper},
|
|
||||||
* so all methods are called on the UI thread.
|
|
||||||
*/
|
|
||||||
private class ControllerResults extends Controller.Result {
|
|
||||||
@Override
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
|
||||||
long mailboxKey, int progress, int numNewMessages,
|
|
||||||
ArrayList<Long> addedMessages) {
|
|
||||||
if (progress == 100) {
|
|
||||||
updateAccounts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMailCallback(MessagingException result, long accountId, long messageId,
|
|
||||||
int progress) {
|
|
||||||
if (progress == 100) {
|
|
||||||
updateAccounts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void deleteAccountCallback(long accountId) {
|
|
||||||
updateAccounts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.R;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This custom View is the list item for the AccountFolderList activity, and serves two purposes:
|
|
||||||
* 1. It's a container to store row metadata
|
|
||||||
* 2. It handles internal clicks so we can create virtual "buttons" in the list
|
|
||||||
*/
|
|
||||||
public class AccountFolderListItem extends LinearLayout {
|
|
||||||
|
|
||||||
public long mAccountId;
|
|
||||||
|
|
||||||
private AccountsAdapter mAdapter;
|
|
||||||
|
|
||||||
private boolean mHasFolderButton;
|
|
||||||
private boolean mDownEvent;
|
|
||||||
private boolean mCachedViewPositions;
|
|
||||||
private int mFolderLeft;
|
|
||||||
|
|
||||||
private final static float FOLDER_PAD = 5.0F;
|
|
||||||
|
|
||||||
public AccountFolderListItem(Context context) {
|
|
||||||
super(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AccountFolderListItem(Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by the adapter at bindView() time
|
|
||||||
*
|
|
||||||
* @param adapter the adapter that creates this view
|
|
||||||
*/
|
|
||||||
public void bindViewInit(AccountsAdapter adapter, boolean hasFolderButton) {
|
|
||||||
mAdapter = adapter;
|
|
||||||
mCachedViewPositions = false;
|
|
||||||
mHasFolderButton = hasFolderButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Overriding this method allows us to "catch" clicks in the checkbox or star
|
|
||||||
* and process them accordingly.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
|
||||||
if (mAdapter.isOnDeletingAccountView(mAccountId)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Short-circuit all of this for list items w/o folder buttons
|
|
||||||
if (!mHasFolderButton) {
|
|
||||||
return super.onTouchEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handled = false;
|
|
||||||
int touchX = (int) event.getX();
|
|
||||||
|
|
||||||
if (!mCachedViewPositions) {
|
|
||||||
float paddingScale = getContext().getResources().getDisplayMetrics().density;
|
|
||||||
int folderPadding = (int) ((FOLDER_PAD * paddingScale) + 0.5);
|
|
||||||
mFolderLeft = findViewById(R.id.folder_button).getLeft() - folderPadding;
|
|
||||||
mCachedViewPositions = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.getAction()) {
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
mDownEvent = true;
|
|
||||||
if (touchX > mFolderLeft) {
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
mDownEvent = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
if (mDownEvent) {
|
|
||||||
if (touchX > mFolderLeft) {
|
|
||||||
mAdapter.onClickFolder(this);
|
|
||||||
handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handled) {
|
|
||||||
postInvalidate();
|
|
||||||
} else {
|
|
||||||
handled = super.onTouchEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,381 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.FolderProperties;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.MergeCursor;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.CursorAdapter;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ListView;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter that presents a combined list of smart mailboxes (e.g. combined inbox, all drafts, etc),
|
|
||||||
* a non-selectable separator, and the list of accounts.
|
|
||||||
*/
|
|
||||||
public class AccountsAdapter extends CursorAdapter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduced mailbox projection used by AccountsAdapter
|
|
||||||
*/
|
|
||||||
public final static String[] MAILBOX_PROJECTION = new String[] {
|
|
||||||
EmailContent.RECORD_ID, MailboxColumns.DISPLAY_NAME,
|
|
||||||
MailboxColumns.ACCOUNT_KEY, MailboxColumns.TYPE,
|
|
||||||
MailboxColumns.UNREAD_COUNT,
|
|
||||||
MailboxColumns.FLAG_VISIBLE, MailboxColumns.FLAGS
|
|
||||||
};
|
|
||||||
public final static int MAILBOX_COLUMN_ID = 0;
|
|
||||||
public final static int MAILBOX_DISPLAY_NAME = 1;
|
|
||||||
public final static int MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
public final static int MAILBOX_TYPE = 3;
|
|
||||||
public final static int MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
public final static int MAILBOX_FLAG_VISIBLE = 5;
|
|
||||||
public final static int MAILBOX_FLAGS = 6;
|
|
||||||
|
|
||||||
private static final String[] MAILBOX_UNREAD_COUNT_PROJECTION = new String [] {
|
|
||||||
MailboxColumns.UNREAD_COUNT
|
|
||||||
};
|
|
||||||
private static final int MAILBOX_UNREAD_COUNT_COLUMN_UNREAD_COUNT = 0;
|
|
||||||
|
|
||||||
private static final String MAILBOX_INBOX_SELECTION =
|
|
||||||
MailboxColumns.ACCOUNT_KEY + " =?" + " AND " + MailboxColumns.TYPE +" = "
|
|
||||||
+ Mailbox.TYPE_INBOX;
|
|
||||||
|
|
||||||
private final LayoutInflater mInflater;
|
|
||||||
private final int mMailboxesCount;
|
|
||||||
private final int mSeparatorPosition;
|
|
||||||
private final long mDefaultAccountId;
|
|
||||||
private final ArrayList<Long> mOnDeletingAccounts = new ArrayList<Long>();
|
|
||||||
private Callback mCallback;
|
|
||||||
|
|
||||||
public static AccountsAdapter getInstance(Cursor mailboxesCursor, Cursor accountsCursor,
|
|
||||||
Context context, long defaultAccountId, Callback callback) {
|
|
||||||
Cursor[] cursors = new Cursor[] { mailboxesCursor, accountsCursor };
|
|
||||||
Cursor mc = new MergeCursor(cursors);
|
|
||||||
return new AccountsAdapter(mc, context, mailboxesCursor.getCount(), defaultAccountId,
|
|
||||||
callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AccountsAdapter(Cursor c, Context context, int mailboxesCount, long defaultAccountId,
|
|
||||||
Callback callback) {
|
|
||||||
super(context, c, true);
|
|
||||||
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
|
||||||
mMailboxesCount = mailboxesCount;
|
|
||||||
mSeparatorPosition = mailboxesCount;
|
|
||||||
mDefaultAccountId = defaultAccountId;
|
|
||||||
mCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When changeCursor(null) is called, drop reference(s) to make sure we don't leak the activity
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void changeCursor(Cursor cursor) {
|
|
||||||
super.changeCursor(cursor);
|
|
||||||
if (cursor == null) {
|
|
||||||
mCallback = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback interface used to report clicks other than the basic list item click or longpress.
|
|
||||||
*/
|
|
||||||
public interface Callback {
|
|
||||||
/**
|
|
||||||
* Callback for clicks on the "folder" icon (to open MailboxList)
|
|
||||||
*/
|
|
||||||
public void onClickAccountFolders(long accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMailbox(int position) {
|
|
||||||
return position < mMailboxesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAccount(int position) {
|
|
||||||
return position > mMailboxesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addOnDeletingAccount(long accountId) {
|
|
||||||
mOnDeletingAccounts.add(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOnDeletingAccountView(long accountId) {
|
|
||||||
return mOnDeletingAccounts.contains(accountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an entry point called by the list item for clicks in the folder "button"
|
|
||||||
*
|
|
||||||
* @param itemView the item in which the click occurred
|
|
||||||
*/
|
|
||||||
public void onClickFolder(AccountFolderListItem itemView) {
|
|
||||||
if (mCallback != null) {
|
|
||||||
mCallback.onClickAccountFolders(itemView.mAccountId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void bindView(View view, Context context, Cursor cursor) {
|
|
||||||
if (cursor.getPosition() < mMailboxesCount) {
|
|
||||||
bindMailboxItem(view, context, cursor, false);
|
|
||||||
} else {
|
|
||||||
bindAccountItem(view, context, cursor, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindMailboxItem(View view, Context context, Cursor cursor, boolean isLastChild)
|
|
||||||
{
|
|
||||||
// Reset the view (in case it was recycled) and prepare for binding
|
|
||||||
AccountFolderListItem itemView = (AccountFolderListItem) view;
|
|
||||||
itemView.bindViewInit(this, false);
|
|
||||||
|
|
||||||
// Invisible (not "gone") to maintain spacing
|
|
||||||
view.findViewById(R.id.chip).setVisibility(View.INVISIBLE);
|
|
||||||
|
|
||||||
String text = cursor.getString(MAILBOX_DISPLAY_NAME);
|
|
||||||
if (text != null) {
|
|
||||||
TextView nameView = (TextView) view.findViewById(R.id.name);
|
|
||||||
nameView.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO get/track live folder status
|
|
||||||
text = null;
|
|
||||||
TextView statusView = (TextView) view.findViewById(R.id.status);
|
|
||||||
if (text != null) {
|
|
||||||
statusView.setText(text);
|
|
||||||
statusView.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
statusView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int count = -1;
|
|
||||||
text = cursor.getString(MAILBOX_UNREAD_COUNT);
|
|
||||||
if (text != null) {
|
|
||||||
count = Integer.valueOf(text);
|
|
||||||
}
|
|
||||||
TextView unreadCountView = (TextView) view.findViewById(R.id.new_message_count);
|
|
||||||
TextView allCountView = (TextView) view.findViewById(R.id.all_message_count);
|
|
||||||
int id = cursor.getInt(MAILBOX_COLUMN_ID);
|
|
||||||
// If the unread count is zero, not to show countView.
|
|
||||||
if (count > 0) {
|
|
||||||
if (id == Mailbox.QUERY_ALL_FAVORITES
|
|
||||||
|| id == Mailbox.QUERY_ALL_DRAFTS
|
|
||||||
|| id == Mailbox.QUERY_ALL_OUTBOX) {
|
|
||||||
unreadCountView.setVisibility(View.GONE);
|
|
||||||
allCountView.setVisibility(View.VISIBLE);
|
|
||||||
allCountView.setText(text);
|
|
||||||
} else {
|
|
||||||
allCountView.setVisibility(View.GONE);
|
|
||||||
unreadCountView.setVisibility(View.VISIBLE);
|
|
||||||
unreadCountView.setText(text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
allCountView.setVisibility(View.GONE);
|
|
||||||
unreadCountView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
view.findViewById(R.id.folder_button).setVisibility(View.GONE);
|
|
||||||
view.findViewById(R.id.folder_separator).setVisibility(View.GONE);
|
|
||||||
view.findViewById(R.id.default_sender).setVisibility(View.GONE);
|
|
||||||
view.findViewById(R.id.folder_icon).setVisibility(View.VISIBLE);
|
|
||||||
((ImageView)view.findViewById(R.id.folder_icon)).setImageDrawable(
|
|
||||||
FolderProperties.getInstance(context).getSummaryMailboxIconIds(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void bindAccountItem(View view, Context context, Cursor cursor, boolean isExpanded)
|
|
||||||
{
|
|
||||||
// Reset the view (in case it was recycled) and prepare for binding
|
|
||||||
AccountFolderListItem itemView = (AccountFolderListItem) view;
|
|
||||||
itemView.bindViewInit(this, true);
|
|
||||||
itemView.mAccountId = cursor.getLong(Account.CONTENT_ID_COLUMN);
|
|
||||||
|
|
||||||
long accountId = cursor.getLong(Account.CONTENT_ID_COLUMN);
|
|
||||||
|
|
||||||
// No color chip for now. TODO Revisit for phone UI
|
|
||||||
view.findViewById(R.id.chip).setVisibility(View.GONE);
|
|
||||||
|
|
||||||
String text = cursor.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
|
|
||||||
if (text != null) {
|
|
||||||
TextView descriptionView = (TextView) view.findViewById(R.id.name);
|
|
||||||
descriptionView.setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
text = cursor.getString(Account.CONTENT_EMAIL_ADDRESS_COLUMN);
|
|
||||||
if (text != null) {
|
|
||||||
TextView emailView = (TextView) view.findViewById(R.id.status);
|
|
||||||
emailView.setText(text);
|
|
||||||
emailView.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: We should not be doing a query inside bindAccountItem
|
|
||||||
int unreadMessageCount = 0;
|
|
||||||
Cursor c = context.getContentResolver().query(Mailbox.CONTENT_URI,
|
|
||||||
MAILBOX_UNREAD_COUNT_PROJECTION,
|
|
||||||
MAILBOX_INBOX_SELECTION,
|
|
||||||
new String[] { String.valueOf(accountId) }, null);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
String count = c.getString(MAILBOX_UNREAD_COUNT_COLUMN_UNREAD_COUNT);
|
|
||||||
if (count != null) {
|
|
||||||
unreadMessageCount = Integer.valueOf(count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
view.findViewById(R.id.all_message_count).setVisibility(View.GONE);
|
|
||||||
TextView unreadCountView = (TextView) view.findViewById(R.id.new_message_count);
|
|
||||||
if (unreadMessageCount > 0) {
|
|
||||||
unreadCountView.setText(String.valueOf(unreadMessageCount));
|
|
||||||
unreadCountView.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
unreadCountView.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
view.findViewById(R.id.folder_icon).setVisibility(View.GONE);
|
|
||||||
view.findViewById(R.id.folder_button).setVisibility(View.VISIBLE);
|
|
||||||
view.findViewById(R.id.folder_separator).setVisibility(View.VISIBLE);
|
|
||||||
if (accountId == mDefaultAccountId) {
|
|
||||||
view.findViewById(R.id.default_sender).setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
view.findViewById(R.id.default_sender).setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
|
||||||
return mInflater.inflate(R.layout.account_folder_list_item, parent, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following series of overrides insert the "Accounts" separator
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prevents the separator view from recycling into the other views
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position) {
|
|
||||||
if (position == mSeparatorPosition) {
|
|
||||||
return IGNORE_ITEM_VIEW_TYPE;
|
|
||||||
}
|
|
||||||
return super.getItemViewType(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Injects the separator view when required, and fudges the cursor for other views
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
// The base class's getView() checks for mDataValid at the beginning, but we don't have
|
|
||||||
// to do that, because if the cursor is invalid getCount() returns 0, in which case this
|
|
||||||
// method wouldn't get called.
|
|
||||||
|
|
||||||
// Handle the separator here - create & bind
|
|
||||||
if (position == mSeparatorPosition) {
|
|
||||||
TextView view;
|
|
||||||
view = (TextView) mInflater.inflate(R.layout.list_separator, parent, false);
|
|
||||||
view.setText(R.string.account_folder_list_separator_accounts);
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
return super.getView(getRealPosition(position), convertView, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forces navigation to skip over the separator
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean areAllItemsEnabled() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forces navigation to skip over the separator
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled(int position) {
|
|
||||||
if (position == mSeparatorPosition) {
|
|
||||||
return false;
|
|
||||||
} else if (isAccount(position)) {
|
|
||||||
Long id = ((MergeCursor)getItem(position)).getLong(Account.CONTENT_ID_COLUMN);
|
|
||||||
return !isOnDeletingAccountView(id);
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adjusts list count to include separator
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
int count = super.getCount();
|
|
||||||
if (count > 0 && (mSeparatorPosition != ListView.INVALID_POSITION)) {
|
|
||||||
// Increment for separator, if we have anything to show.
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts list position to cursor position
|
|
||||||
*/
|
|
||||||
private int getRealPosition(int pos) {
|
|
||||||
if (mSeparatorPosition == ListView.INVALID_POSITION) {
|
|
||||||
// No separator, identity map
|
|
||||||
return pos;
|
|
||||||
} else if (pos <= mSeparatorPosition) {
|
|
||||||
// Before or at the separator, identity map
|
|
||||||
return pos;
|
|
||||||
} else {
|
|
||||||
// After the separator, remove 1 from the pos to get the real underlying pos
|
|
||||||
return pos - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the item using external position numbering (no separator)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Object getItem(int pos) {
|
|
||||||
return super.getItem(getRealPosition(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the item id using external position numbering (no separator)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public long getItemId(int pos) {
|
|
||||||
return super.getItemId(getRealPosition(pos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -134,17 +134,4 @@ public final class ActivityHelper {
|
||||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateRefreshMenuIcon(MenuItem item, boolean show, boolean animate) {
|
|
||||||
if (show) {
|
|
||||||
item.setVisible(true);
|
|
||||||
if (animate) {
|
|
||||||
item.setActionView(R.layout.action_bar_indeterminate_progress);
|
|
||||||
} else {
|
|
||||||
item.setActionView(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
item.setVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import com.android.email.Controller;
|
||||||
import com.android.email.ControllerResultUiThreadWrapper;
|
import com.android.email.ControllerResultUiThreadWrapper;
|
||||||
import com.android.email.Email;
|
import com.android.email.Email;
|
||||||
import com.android.email.MessagingExceptionStrings;
|
import com.android.email.MessagingExceptionStrings;
|
||||||
import com.android.email.NotificationController;
|
|
||||||
import com.android.email.R;
|
import com.android.email.R;
|
||||||
import com.android.emailcommon.Logging;
|
import com.android.emailcommon.Logging;
|
||||||
import com.android.emailcommon.mail.MessagingException;
|
import com.android.emailcommon.mail.MessagingException;
|
||||||
|
|
|
@ -1,331 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.Controller;
|
|
||||||
import com.android.email.ControllerResultUiThreadWrapper;
|
|
||||||
import com.android.email.Email;
|
|
||||||
import com.android.email.MessagingExceptionStrings;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.email.RefreshManager;
|
|
||||||
import com.android.email.activity.setup.AccountSettingsXL;
|
|
||||||
import com.android.emailcommon.mail.MessagingException;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.AccountColumns;
|
|
||||||
import com.android.emailcommon.utility.Utility;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
// TODO: This has a lot in common with MessageList --should we merge them somehow?
|
|
||||||
// But maybe we'll need to move to a single activity style anyway -- let's not worry about it too
|
|
||||||
// much for now. We might even completely ditch this activity and switch to a dialog.
|
|
||||||
public class MailboxList extends Activity implements MailboxListFragment.Callback {
|
|
||||||
|
|
||||||
// Intent extras (internal to this activity)
|
|
||||||
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity._ACCOUNT_ID";
|
|
||||||
|
|
||||||
// UI support
|
|
||||||
private ActionBar mActionBar;
|
|
||||||
private TextView mErrorBanner;
|
|
||||||
private MailboxListFragment mListFragment;
|
|
||||||
|
|
||||||
private Controller.Result mControllerCallback;
|
|
||||||
|
|
||||||
// DB access
|
|
||||||
private long mAccountId;
|
|
||||||
private AsyncTask<Void, Void, String[]> mLoadAccountNameTask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a specific account.
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param accountId the account to view
|
|
||||||
*/
|
|
||||||
public static void actionHandleAccount(Context context, long accountId) {
|
|
||||||
Intent intent = new Intent(context, MailboxList.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
|
||||||
context.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle icicle) {
|
|
||||||
super.onCreate(icicle);
|
|
||||||
ActivityHelper.debugSetWindowFlags(this);
|
|
||||||
|
|
||||||
mAccountId = getIntent().getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
|
||||||
if (mAccountId == -1) {
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
|
||||||
setContentView(R.layout.mailbox_list);
|
|
||||||
|
|
||||||
mControllerCallback = new ControllerResultUiThreadWrapper<ControllerResults>(
|
|
||||||
new Handler(), new ControllerResults());
|
|
||||||
mActionBar = getActionBar();
|
|
||||||
mErrorBanner = (TextView) findViewById(R.id.connection_error_text);
|
|
||||||
mListFragment = (MailboxListFragment) getFragmentManager()
|
|
||||||
.findFragmentById(R.id.mailbox_list_fragment);
|
|
||||||
|
|
||||||
mActionBar.setTitle(R.string.mailbox_list_title);
|
|
||||||
mListFragment.setCallback(this);
|
|
||||||
mListFragment.openMailboxes(mAccountId, -1);
|
|
||||||
|
|
||||||
// Halt the progress indicator (we'll display it later when needed)
|
|
||||||
setProgressBarIndeterminate(true);
|
|
||||||
setProgressBarIndeterminateVisibility(false);
|
|
||||||
|
|
||||||
// Go to the database for the account name
|
|
||||||
mLoadAccountNameTask = new AsyncTask<Void, Void, String[]>() {
|
|
||||||
@Override
|
|
||||||
protected String[] doInBackground(Void... params) {
|
|
||||||
String accountName = null;
|
|
||||||
Uri uri = ContentUris.withAppendedId(Account.CONTENT_URI, mAccountId);
|
|
||||||
Cursor c = MailboxList.this.getContentResolver().query(
|
|
||||||
uri, new String[] { AccountColumns.DISPLAY_NAME }, null, null, null);
|
|
||||||
try {
|
|
||||||
if (c.moveToFirst()) {
|
|
||||||
accountName = c.getString(0);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
c.close();
|
|
||||||
}
|
|
||||||
return new String[] { accountName };
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(String[] result) {
|
|
||||||
if (result == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final String accountName = (String) result[0];
|
|
||||||
// accountName is null if account name can't be retrieved or query exception
|
|
||||||
if (accountName == null) {
|
|
||||||
// something is wrong with this account
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
mActionBar.setTitle(R.string.mailbox_list_title);
|
|
||||||
mActionBar.setSubtitle(accountName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}.execute();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
Controller.getInstance(getApplication()).removeResultCallback(mControllerCallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
Controller.getInstance(getApplication()).addResultCallback(mControllerCallback);
|
|
||||||
|
|
||||||
// Exit immediately if the accounts list has changed (e.g. externally deleted)
|
|
||||||
if (Email.getNotifyUiAccountsChanged()) {
|
|
||||||
Welcome.actionStart(this);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
Utility.cancelTaskInterrupt(mLoadAccountNameTask);
|
|
||||||
mLoadAccountNameTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
super.onCreateOptionsMenu(menu);
|
|
||||||
getMenuInflater().inflate(R.menu.mailbox_list_option, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
onAccounts();
|
|
||||||
return true;
|
|
||||||
case R.id.refresh:
|
|
||||||
onRefresh();
|
|
||||||
return true;
|
|
||||||
case R.id.compose:
|
|
||||||
onCompose();
|
|
||||||
return true;
|
|
||||||
case R.id.account_settings:
|
|
||||||
onEditAccount();
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements MailboxFragment.Callback
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onMailboxSelected(long accountId, long mailboxId, boolean navigate,
|
|
||||||
boolean dragDrop) {
|
|
||||||
// TODO handle folder navigation on the phone. when will we actually show the messages?
|
|
||||||
onOpenMailbox(mailboxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements MailboxFragment.Callback
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onAccountSelected(long accountId) {
|
|
||||||
// Only used on the Combined view, which isn't used on the phone UI.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements MailboxFragment.Callback
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh the mailbox list
|
|
||||||
*/
|
|
||||||
private void onRefresh() {
|
|
||||||
Controller controller = Controller.getInstance(getApplication());
|
|
||||||
showProgressIcon(true);
|
|
||||||
RefreshManager.getInstance(this).refreshMailboxList(mAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onAccounts() {
|
|
||||||
AccountFolderList.actionShowAccounts(this);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onEditAccount() {
|
|
||||||
AccountSettingsXL.actionSettings(this, mAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onOpenMailbox(long mailboxId) {
|
|
||||||
MessageList.actionHandleMailbox(this, mailboxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onCompose() {
|
|
||||||
MessageCompose.actionCompose(this, mAccountId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showProgressIcon(boolean show) {
|
|
||||||
setProgressBarIndeterminateVisibility(show);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showErrorBanner(String message) {
|
|
||||||
boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE;
|
|
||||||
if (message != null) {
|
|
||||||
mErrorBanner.setText(message);
|
|
||||||
if (!isVisible) {
|
|
||||||
mErrorBanner.setVisibility(View.VISIBLE);
|
|
||||||
mErrorBanner.startAnimation(
|
|
||||||
AnimationUtils.loadAnimation(
|
|
||||||
MailboxList.this, R.anim.header_appear));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isVisible) {
|
|
||||||
mErrorBanner.setVisibility(View.GONE);
|
|
||||||
mErrorBanner.startAnimation(
|
|
||||||
AnimationUtils.loadAnimation(
|
|
||||||
MailboxList.this, R.anim.header_disappear));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller results listener. We wrap it with {@link ControllerResultUiThreadWrapper},
|
|
||||||
* so all methods are called on the UI thread.
|
|
||||||
*/
|
|
||||||
private class ControllerResults extends Controller.Result {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMailboxListCallback(MessagingException result, long accountKey,
|
|
||||||
int progress) {
|
|
||||||
if (accountKey == mAccountId) {
|
|
||||||
updateBanner(result, progress);
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMailboxCallback(MessagingException result, long accountKey,
|
|
||||||
long mailboxKey, int progress, int numNewMessages, ArrayList<Long> addedMessages) {
|
|
||||||
if (accountKey == mAccountId) {
|
|
||||||
updateBanner(result, progress);
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMailCallback(MessagingException result, long accountId, long messageId,
|
|
||||||
int progress) {
|
|
||||||
if (accountId == mAccountId) {
|
|
||||||
updateBanner(result, progress);
|
|
||||||
updateProgress(result, progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgress(MessagingException result, int progress) {
|
|
||||||
showProgressIcon(result == null && progress < 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show or hide the connection error banner, and convert the various MessagingException
|
|
||||||
* variants into localizable text. There is hysteresis in the show/hide logic: Once shown,
|
|
||||||
* the banner will remain visible until some progress is made on the connection. The
|
|
||||||
* goal is to keep it from flickering during retries in a bad connection state.
|
|
||||||
*
|
|
||||||
* @param result
|
|
||||||
* @param progress
|
|
||||||
*/
|
|
||||||
private void updateBanner(MessagingException result, int progress) {
|
|
||||||
if (result != null) {
|
|
||||||
showErrorBanner(
|
|
||||||
MessagingExceptionStrings.getErrorString(MailboxList.this, result));
|
|
||||||
} else if (progress > 0) {
|
|
||||||
showErrorBanner(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,354 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2009 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.Email;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.email.RefreshManager;
|
|
||||||
import com.android.email.activity.setup.AccountSecurity;
|
|
||||||
import com.android.email.activity.setup.AccountSettingsXL;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class MessageList extends Activity implements MessageListFragment.Callback {
|
|
||||||
// Intent extras (internal to this activity)
|
|
||||||
private static final String EXTRA_ACCOUNT_ID = "com.android.email.activity._ACCOUNT_ID";
|
|
||||||
private static final String EXTRA_MAILBOX_TYPE = "com.android.email.activity.MAILBOX_TYPE";
|
|
||||||
private static final String EXTRA_MAILBOX_ID = "com.android.email.activity.MAILBOX_ID";
|
|
||||||
|
|
||||||
private static final int REQUEST_SECURITY = 0;
|
|
||||||
|
|
||||||
// UI support
|
|
||||||
private MessageListFragment mListFragment;
|
|
||||||
private TextView mErrorBanner;
|
|
||||||
|
|
||||||
private RefreshManager mRefreshManager;
|
|
||||||
private final RefreshListener mRefreshListener = new RefreshListener();
|
|
||||||
|
|
||||||
private MailboxFinder mMailboxFinder;
|
|
||||||
private final MailboxFinderCallback mMailboxFinderCallback = new MailboxFinderCallback();
|
|
||||||
|
|
||||||
/* package */ MessageListFragment getListFragmentForTest() {
|
|
||||||
return mListFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a specific mailbox.
|
|
||||||
*
|
|
||||||
* TODO This should just shortcut to a more generic version that can accept a list of
|
|
||||||
* accounts/mailboxes (e.g. merged inboxes).
|
|
||||||
*
|
|
||||||
* @param context
|
|
||||||
* @param mailboxType mailbox key
|
|
||||||
*/
|
|
||||||
public static void actionHandleMailbox(Context context, long mailboxType) {
|
|
||||||
context.startActivity(createIntent(context, -1, mailboxType, -1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a specific mailbox by account & type
|
|
||||||
*
|
|
||||||
* @param context The caller's context (for generating an intent)
|
|
||||||
* @param accountId The account to open
|
|
||||||
* @param mailboxType the type of mailbox to open (e.g. @see EmailContent.Mailbox.TYPE_INBOX)
|
|
||||||
*/
|
|
||||||
public static void actionHandleAccount(Context context, long accountId, int mailboxType) {
|
|
||||||
context.startActivity(createIntent(context, accountId, -1, mailboxType));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return an intent to open a specific mailbox by account & type.
|
|
||||||
*
|
|
||||||
* @param context The caller's context (for generating an intent)
|
|
||||||
* @param accountId The account to open, or -1
|
|
||||||
* @param mailboxId the ID of the mailbox to open, or -1
|
|
||||||
* @param mailboxType the type of mailbox to open (e.g. @see Mailbox.TYPE_INBOX) or -1
|
|
||||||
*/
|
|
||||||
public static Intent createIntent(Context context, long accountId, long mailboxId,
|
|
||||||
int mailboxType) {
|
|
||||||
Intent intent = new Intent(context, MessageList.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
if (accountId != -1) intent.putExtra(EXTRA_ACCOUNT_ID, accountId);
|
|
||||||
if (mailboxId != -1) intent.putExtra(EXTRA_MAILBOX_ID, mailboxId);
|
|
||||||
if (mailboxType != -1) intent.putExtra(EXTRA_MAILBOX_TYPE, mailboxType);
|
|
||||||
return intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle icicle) {
|
|
||||||
super.onCreate(icicle);
|
|
||||||
ActivityHelper.debugSetWindowFlags(this);
|
|
||||||
setContentView(R.layout.message_list);
|
|
||||||
|
|
||||||
mRefreshManager = RefreshManager.getInstance(this);
|
|
||||||
mRefreshManager.registerListener(mRefreshListener);
|
|
||||||
mListFragment = (MessageListFragment) getFragmentManager()
|
|
||||||
.findFragmentById(R.id.message_list_fragment);
|
|
||||||
mErrorBanner = (TextView) findViewById(R.id.connection_error_text);
|
|
||||||
|
|
||||||
mListFragment.setCallback(this);
|
|
||||||
|
|
||||||
// Show the appropriate account/mailbox specified by an {@link Intent}.
|
|
||||||
selectAccountAndMailbox(getIntent());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the appropriate account/mailbox specified by an {@link Intent}.
|
|
||||||
*/
|
|
||||||
private void selectAccountAndMailbox(Intent intent) {
|
|
||||||
long mailboxId = intent.getLongExtra(EXTRA_MAILBOX_ID, -1);
|
|
||||||
if (mailboxId != -1) {
|
|
||||||
mListFragment.openMailbox(mailboxId);
|
|
||||||
} else {
|
|
||||||
int mailboxType = intent.getIntExtra(EXTRA_MAILBOX_TYPE, Mailbox.TYPE_INBOX);
|
|
||||||
Uri uri = intent.getData();
|
|
||||||
// TODO Possible ANR. getAccountIdFromShortcutSafeUri accesses DB.
|
|
||||||
long accountId = (uri == null) ? -1
|
|
||||||
: Account.getAccountIdFromShortcutSafeUri(this, uri);
|
|
||||||
if (accountId == -1) {
|
|
||||||
accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
|
|
||||||
}
|
|
||||||
if (accountId == -1) {
|
|
||||||
launchWelcomeAndFinish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mMailboxFinder = new MailboxFinder(this, accountId, mailboxType,
|
|
||||||
mMailboxFinderCallback);
|
|
||||||
mMailboxFinder.startLookup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
// Exit immediately if the accounts list has changed (e.g. externally deleted)
|
|
||||||
if (Email.getNotifyUiAccountsChanged()) {
|
|
||||||
Welcome.actionStart(this);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
if (mMailboxFinder != null) {
|
|
||||||
mMailboxFinder.cancel();
|
|
||||||
mMailboxFinder = null;
|
|
||||||
}
|
|
||||||
mRefreshManager.unregisterListener(mRefreshListener);
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void launchWelcomeAndFinish() {
|
|
||||||
Welcome.actionStart(this);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onListLoaded() {
|
|
||||||
// Now we know if the mailbox is refreshable
|
|
||||||
updateProgressIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when the list fragment can't find mailbox/account.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onMailboxNotFound() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageOpen(long messageId, long messageMailboxId, long listMailboxId, int type) {
|
|
||||||
if (type == MessageListFragment.Callback.TYPE_DRAFT) {
|
|
||||||
MessageCompose.actionEditDraft(this, messageId);
|
|
||||||
} else {
|
|
||||||
// WARNING: here we pass "listMailboxId", which can be the negative id of
|
|
||||||
// a combined mailbox, instead of the mailboxId of the particular message that
|
|
||||||
// is opened. This is to support the next/prev buttons on the message view
|
|
||||||
// properly even for combined mailboxes.
|
|
||||||
MessageView.actionView(this, messageId, listMailboxId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnterSelectionMode(boolean enter) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAdvancingOpAccepted(Set<Long> affectedMessages) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
getMenuInflater().inflate(R.menu.message_list_option, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
||||||
// this method can be called in the very early stage of the activity lifecycle, where
|
|
||||||
// mListFragment isn't ready yet.
|
|
||||||
boolean show = (mListFragment != null) && mListFragment.isRefreshable();
|
|
||||||
boolean animate = (mListFragment != null) && mRefreshManager.isMessageListRefreshing(
|
|
||||||
mListFragment.getMailboxId());
|
|
||||||
ActivityHelper.updateRefreshMenuIcon(menu.findItem(R.id.refresh), show, animate);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.refresh:
|
|
||||||
mListFragment.onRefresh(true);
|
|
||||||
return true;
|
|
||||||
case R.id.folders:
|
|
||||||
onFolders();
|
|
||||||
return true;
|
|
||||||
case R.id.accounts:
|
|
||||||
onAccounts();
|
|
||||||
return true;
|
|
||||||
case R.id.compose:
|
|
||||||
onCompose();
|
|
||||||
return true;
|
|
||||||
case R.id.account_settings:
|
|
||||||
onEditAccount();
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFolders() {
|
|
||||||
long accountId = mListFragment.getAccountId();
|
|
||||||
// accountId will be -1 when a) mailbox is still loading, or for magic mailboxes.
|
|
||||||
if (accountId != -1) {
|
|
||||||
MailboxList.actionHandleAccount(this, accountId);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onAccounts() {
|
|
||||||
AccountFolderList.actionShowAccounts(this);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onCompose() {
|
|
||||||
// Passing account = -1 is okay -- the default account will be used.
|
|
||||||
MessageCompose.actionCompose(this, mListFragment.getAccountId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onEditAccount() {
|
|
||||||
// Passing account = -1 is okay
|
|
||||||
AccountSettingsXL.actionSettings(this, mListFragment.getAccountId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the eventual result from the security update activity
|
|
||||||
*
|
|
||||||
* Note, this is extremely coarse, and it simply returns the user to the Accounts list.
|
|
||||||
* Anything more requires refactoring of this Activity.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
|
||||||
switch (requestCode) {
|
|
||||||
case REQUEST_SECURITY:
|
|
||||||
onAccounts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgressIcon() {
|
|
||||||
invalidateOptionsMenu(); // animate/stop refreshing icon
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showErrorBanner(String message) {
|
|
||||||
boolean isVisible = mErrorBanner.getVisibility() == View.VISIBLE;
|
|
||||||
if (!TextUtils.isEmpty(message)) {
|
|
||||||
mErrorBanner.setText(message);
|
|
||||||
if (!isVisible) {
|
|
||||||
mErrorBanner.setVisibility(View.VISIBLE);
|
|
||||||
mErrorBanner.startAnimation(
|
|
||||||
AnimationUtils.loadAnimation(
|
|
||||||
MessageList.this, R.anim.header_appear));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isVisible) {
|
|
||||||
mErrorBanner.setVisibility(View.GONE);
|
|
||||||
mErrorBanner.startAnimation(
|
|
||||||
AnimationUtils.loadAnimation(
|
|
||||||
MessageList.this, R.anim.header_disappear));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RefreshListener implements RefreshManager.Listener {
|
|
||||||
@Override
|
|
||||||
public void onMessagingError(long accountId, long mailboxId, String message) {
|
|
||||||
updateProgressIcon();
|
|
||||||
showErrorBanner(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRefreshStatusChanged(long accountId, long mailboxId) {
|
|
||||||
updateProgressIcon();
|
|
||||||
showErrorBanner(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MailboxFinderCallback implements MailboxFinder.Callback {
|
|
||||||
@Override
|
|
||||||
public void onMailboxFound(long accountId, long mailboxId) {
|
|
||||||
mListFragment.openMailbox(mailboxId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAccountNotFound() {
|
|
||||||
// Let the Welcome activity show the default screen.
|
|
||||||
launchWelcomeAndFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMailboxNotFound(long accountId) {
|
|
||||||
// Let the Welcome activity show the default screen.
|
|
||||||
launchWelcomeAndFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAccountSecurityHold(long accountId) {
|
|
||||||
// launch the security setup activity
|
|
||||||
Intent i = AccountSecurity.actionUpdateSecurityIntent(
|
|
||||||
MessageList.this, accountId, true);
|
|
||||||
startActivityForResult(i, REQUEST_SECURITY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1263,7 +1263,7 @@ public class MessageListFragment extends ListFragment
|
||||||
mSelectionMode = mode;
|
mSelectionMode = mode;
|
||||||
|
|
||||||
MenuInflater inflater = getActivity().getMenuInflater();
|
MenuInflater inflater = getActivity().getMenuInflater();
|
||||||
inflater.inflate(R.menu.message_list_selection_mode, menu);
|
inflater.inflate(R.menu.message_list_fragment_cab_options, menu);
|
||||||
mMarkRead = menu.findItem(R.id.mark_read);
|
mMarkRead = menu.findItem(R.id.mark_read);
|
||||||
mMarkUnread = menu.findItem(R.id.mark_unread);
|
mMarkUnread = menu.findItem(R.id.mark_unread);
|
||||||
mAddStar = menu.findItem(R.id.add_star);
|
mAddStar = menu.findItem(R.id.add_star);
|
||||||
|
|
|
@ -1,374 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.Email;
|
|
||||||
import com.android.email.Preferences;
|
|
||||||
import com.android.email.R;
|
|
||||||
import com.android.emailcommon.Logging;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Activity to show (non-EML) email messages.
|
|
||||||
*
|
|
||||||
* This activity shows regular email messages, which are not file-based. (i.e. not *.eml or *.msg)
|
|
||||||
*
|
|
||||||
* See {@link MessageViewBase} for the class relation diagram.
|
|
||||||
*/
|
|
||||||
public class MessageView extends MessageViewBase implements View.OnClickListener,
|
|
||||||
MessageOrderManager.Callback, MessageViewFragment.Callback {
|
|
||||||
private static final String EXTRA_MESSAGE_ID = "com.android.email.MessageView_message_id";
|
|
||||||
private static final String EXTRA_MAILBOX_ID = "com.android.email.MessageView_mailbox_id";
|
|
||||||
|
|
||||||
// for saveInstanceState()
|
|
||||||
private static final String STATE_MESSAGE_ID = "messageId";
|
|
||||||
|
|
||||||
private long mMessageId;
|
|
||||||
private long mMailboxId;
|
|
||||||
|
|
||||||
private MessageOrderManager mOrderManager;
|
|
||||||
|
|
||||||
private MessageViewFragment mFragment;
|
|
||||||
|
|
||||||
private View mMoveToNewer;
|
|
||||||
private View mMoveToOlder;
|
|
||||||
private View mReplyButton;
|
|
||||||
private View mReplyAllButton;
|
|
||||||
|
|
||||||
// False when a message can't be forwarded/replied, such as trashed messages
|
|
||||||
private boolean mReplyAndForwardEnabled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View a specific message found in the Email provider.
|
|
||||||
* @param messageId the message to view.
|
|
||||||
* @param mailboxId identifies the sequence of messages used for newer/older navigation.
|
|
||||||
*/
|
|
||||||
public static void actionView(Context context, long messageId, long mailboxId) {
|
|
||||||
context.startActivity(getActionViewIntent(context, messageId, mailboxId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Intent getActionViewIntent(Context context, long messageId, long mailboxId) {
|
|
||||||
if (messageId < 0) {
|
|
||||||
throw new IllegalArgumentException("MessageView invalid messageId " + messageId);
|
|
||||||
}
|
|
||||||
Intent i = new Intent(context, MessageView.class);
|
|
||||||
i.putExtra(EXTRA_MESSAGE_ID, messageId);
|
|
||||||
i.putExtra(EXTRA_MAILBOX_ID, mailboxId);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected int getLayoutId() {
|
|
||||||
return R.layout.message_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle icicle) {
|
|
||||||
super.onCreate(icicle);
|
|
||||||
|
|
||||||
mFragment = (MessageViewFragment) getFragmentManager()
|
|
||||||
.findFragmentById(R.id.message_view_fragment);
|
|
||||||
mFragment.setCallback(this);
|
|
||||||
|
|
||||||
mMoveToNewer = UiUtilities.getView(this, R.id.moveToNewer);
|
|
||||||
mMoveToOlder = UiUtilities.getView(this, R.id.moveToOlder);
|
|
||||||
mMoveToNewer.setOnClickListener(this);
|
|
||||||
mMoveToOlder.setOnClickListener(this);
|
|
||||||
mReplyButton = UiUtilities.getView(this, R.id.reply);
|
|
||||||
mReplyAllButton = UiUtilities.getView(this, R.id.reply_all);
|
|
||||||
|
|
||||||
initFromIntent();
|
|
||||||
if (icicle != null) {
|
|
||||||
mMessageId = icicle.getLong(STATE_MESSAGE_ID, mMessageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initFromIntent() {
|
|
||||||
Intent intent = getIntent();
|
|
||||||
mMessageId = intent.getLongExtra(EXTRA_MESSAGE_ID, -1);
|
|
||||||
mMailboxId = intent.getLongExtra(EXTRA_MAILBOX_ID, -1);
|
|
||||||
if (mMessageId == -1 || mMailboxId == -1) {
|
|
||||||
Log.w(Logging.LOG_TAG, "Insufficient intent parameter. Closing...");
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enableForwardReply(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onSaveInstanceState(Bundle state) {
|
|
||||||
super.onSaveInstanceState(state);
|
|
||||||
if (mMessageId != -1) {
|
|
||||||
state.putLong(STATE_MESSAGE_ID, mMessageId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
// Exit immediately if the accounts list has changed (e.g. externally deleted)
|
|
||||||
if (Email.getNotifyUiAccountsChanged()) {
|
|
||||||
Welcome.actionStart(this);
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mOrderManager = new MessageOrderManager(this, mMailboxId, this);
|
|
||||||
messageChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
if (mOrderManager != null) {
|
|
||||||
mOrderManager.close();
|
|
||||||
mOrderManager = null;
|
|
||||||
}
|
|
||||||
super.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note the return type is a subclass of that of the super class method.
|
|
||||||
@Override
|
|
||||||
protected MessageViewFragment getFragment() {
|
|
||||||
return mFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected long getAccountId() {
|
|
||||||
return getFragment().getAccountId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageViewShown(int mailboxType) {
|
|
||||||
super.onMessageViewShown(mailboxType);
|
|
||||||
enableForwardReply(mailboxType != Mailbox.TYPE_TRASH);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onDeleteMessage() {
|
|
||||||
// the delete triggers mCursorObserver in MessageOrderManager.
|
|
||||||
// first move to older/newer before the actual delete
|
|
||||||
long messageIdToDelete = mMessageId;
|
|
||||||
|
|
||||||
boolean moved = autoAdvance();
|
|
||||||
ActivityHelper.deleteMessage(this, messageIdToDelete);
|
|
||||||
if (!moved) {
|
|
||||||
// this generates a benign warning "Duplicate finish request" because
|
|
||||||
// MessageOrderManager detects that the current message is gone, and we finish() it
|
|
||||||
// in the onMessageNotFound() callback.
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-advances the message being shown according to the auto-advance policy set in preferences
|
|
||||||
* @return Whether or not a new message was selected. This will return false either if there are
|
|
||||||
* no appropriate messages to advance to, or if the preferences indicate we should not
|
|
||||||
* auto-advance
|
|
||||||
*/
|
|
||||||
private boolean autoAdvance() {
|
|
||||||
switch (Preferences.getPreferences(this).getAutoAdvanceDirection()) {
|
|
||||||
case Preferences.AUTO_ADVANCE_NEWER:
|
|
||||||
return moveToNewer();
|
|
||||||
case Preferences.AUTO_ADVANCE_OLDER:
|
|
||||||
return moveToOlder();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean moveToOlder() {
|
|
||||||
if (mOrderManager != null && mOrderManager.moveToOlder()) {
|
|
||||||
mMessageId = mOrderManager.getCurrentMessageId();
|
|
||||||
messageChanged();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean moveToNewer() {
|
|
||||||
if (mOrderManager != null && mOrderManager.moveToNewer()) {
|
|
||||||
mMessageId = mOrderManager.getCurrentMessageId();
|
|
||||||
messageChanged();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onClick(View view) {
|
|
||||||
switch (view.getId()) {
|
|
||||||
case R.id.reply:
|
|
||||||
onReply();
|
|
||||||
break;
|
|
||||||
case R.id.reply_all:
|
|
||||||
onReplyAll();
|
|
||||||
break;
|
|
||||||
case R.id.delete:
|
|
||||||
onDeleteMessage();
|
|
||||||
break;
|
|
||||||
case R.id.moveToOlder:
|
|
||||||
moveToOlder();
|
|
||||||
break;
|
|
||||||
case R.id.moveToNewer:
|
|
||||||
moveToNewer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
boolean handled = handleMenuItem(item.getItemId());
|
|
||||||
if (!handled) {
|
|
||||||
handled = super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
return handled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is the core functionality of onOptionsItemSelected() but broken out and exposed
|
|
||||||
* for testing purposes (because it's annoying to mock a MenuItem).
|
|
||||||
*
|
|
||||||
* @param menuItemId id that was clicked
|
|
||||||
* @return true if handled here
|
|
||||||
*/
|
|
||||||
/* package */ boolean handleMenuItem(int menuItemId) {
|
|
||||||
switch (menuItemId) {
|
|
||||||
case R.id.delete:
|
|
||||||
onDeleteMessage();
|
|
||||||
break;
|
|
||||||
case R.id.reply:
|
|
||||||
onReply();
|
|
||||||
break;
|
|
||||||
case R.id.reply_all:
|
|
||||||
onReplyAll();
|
|
||||||
break;
|
|
||||||
case R.id.forward:
|
|
||||||
onForward();
|
|
||||||
break;
|
|
||||||
case R.id.mark_as_unread:
|
|
||||||
getFragment().onMarkMessageAsRead(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessageSetUnread() {
|
|
||||||
if (!autoAdvance()) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableForwardReply(boolean enabled) {
|
|
||||||
mReplyAndForwardEnabled = enabled;
|
|
||||||
mReplyButton.setEnabled(enabled);
|
|
||||||
mReplyAllButton.setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
|
||||||
super.onCreateOptionsMenu(menu);
|
|
||||||
getMenuInflater().inflate(R.menu.message_view_option, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
|
||||||
menu.findItem(R.id.forward).setEnabled(mReplyAndForwardEnabled);
|
|
||||||
menu.findItem(R.id.reply).setEnabled(mReplyAndForwardEnabled);
|
|
||||||
menu.findItem(R.id.reply_all).setEnabled(mReplyAndForwardEnabled);
|
|
||||||
return super.onPrepareOptionsMenu(menu);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sync the current message.
|
|
||||||
* - Set message id to the fragment and the message order manager.
|
|
||||||
* - Update the navigation arrows.
|
|
||||||
*/
|
|
||||||
private void messageChanged() {
|
|
||||||
getFragment().openMessage(mMessageId);
|
|
||||||
if (mOrderManager != null) {
|
|
||||||
mOrderManager.moveTo(mMessageId);
|
|
||||||
}
|
|
||||||
updateNavigationArrows();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the arrows based on the current position of the older/newer cursor.
|
|
||||||
*/
|
|
||||||
private void updateNavigationArrows() {
|
|
||||||
mMoveToNewer.setEnabled((mOrderManager != null) && mOrderManager.canMoveToNewer());
|
|
||||||
mMoveToOlder.setEnabled((mOrderManager != null) && mOrderManager.canMoveToOlder());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Implements {@link MessageOrderManager.Callback#onMessageNotFound()}. */
|
|
||||||
// TODO Name too generic. Rename this.
|
|
||||||
@Override
|
|
||||||
public void onMessageNotFound() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Implements {@link MessageOrderManager.Callback#onMessagesChanged()}. */
|
|
||||||
// TODO Name too generic. Rename this.
|
|
||||||
@Override
|
|
||||||
public void onMessagesChanged() {
|
|
||||||
updateNavigationArrows();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRespondedToInvite(int response) {
|
|
||||||
if (!autoAdvance()) {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCalendarLinkClicked(long epochEventStartTime) {
|
|
||||||
ActivityHelper.openCalendar(this, epochEventStartTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReply() {
|
|
||||||
MessageCompose.actionReply(this, mMessageId, false);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReplyAll() {
|
|
||||||
MessageCompose.actionReply(this, mMessageId, true);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onForward() {
|
|
||||||
MessageCompose.actionForward(this, mMessageId);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBeforeMessageGone() {
|
|
||||||
// TODO Implement this
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,37 +17,14 @@
|
||||||
package com.android.email.activity;
|
package com.android.email.activity;
|
||||||
|
|
||||||
import com.android.email.Controller;
|
import com.android.email.Controller;
|
||||||
import com.android.email.R;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for {@link MessageView} and {@link MessageFileView}.
|
* TODO Now that MessageView is gone, we can merge it with {@link MessageFileView}.
|
||||||
*
|
|
||||||
* Class relation diagram:
|
|
||||||
* <pre>
|
|
||||||
* (activities) (fragments)
|
|
||||||
* MessageViewBase MessageViewFragmentBase
|
|
||||||
* | | (with nested interface Callback)
|
|
||||||
* | |
|
|
||||||
* |-- MessageFileView -- owns --> |-- MessageFileViewFragment : For EML files.
|
|
||||||
* | | (with nested interface Callback, which implements
|
|
||||||
* | | MessageViewFragmentBase.Callback)
|
|
||||||
* | |
|
|
||||||
* |-- MessageView -- owns --> |-- MessageViewFragment : For regular messages
|
|
||||||
*
|
|
||||||
* MessageView is basically same as MessageFileView, but has more operations, such as "delete",
|
|
||||||
* "forward", "reply", etc.
|
|
||||||
*
|
|
||||||
* Similarly, MessageViewFragment has more operations than MessageFileViewFragment does, such as
|
|
||||||
* "mark unread", "respond to invite", etc. Also its Callback interface has more method than
|
|
||||||
* MessageViewFragmentBase.Callback does, for the extra operations.
|
|
||||||
* </pre>
|
|
||||||
*/
|
*/
|
||||||
public abstract class MessageViewBase extends Activity implements MessageViewFragmentBase.Callback {
|
public abstract class MessageViewBase extends Activity implements MessageViewFragmentBase.Callback {
|
||||||
private ProgressDialog mFetchAttachmentProgressDialog;
|
|
||||||
private Controller mController;
|
private Controller mController;
|
||||||
|
|
||||||
protected abstract int getLayoutId();
|
protected abstract int getLayoutId();
|
||||||
|
@ -58,12 +35,6 @@ public abstract class MessageViewBase extends Activity implements MessageViewFra
|
||||||
ActivityHelper.debugSetWindowFlags(this);
|
ActivityHelper.debugSetWindowFlags(this);
|
||||||
setContentView(getLayoutId());
|
setContentView(getLayoutId());
|
||||||
|
|
||||||
// TODO Turn it into a "managed" dialog?
|
|
||||||
// Managed dialogs survive activity re-creation. (e.g. orientation change)
|
|
||||||
mFetchAttachmentProgressDialog = new ProgressDialog(this);
|
|
||||||
mFetchAttachmentProgressDialog.setIndeterminate(true);
|
|
||||||
mFetchAttachmentProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
|
||||||
|
|
||||||
mController = Controller.getInstance(getApplication());
|
mController = Controller.getInstance(getApplication());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,12 +17,15 @@
|
||||||
package com.android.email.activity;
|
package com.android.email.activity;
|
||||||
|
|
||||||
import com.android.email.Email;
|
import com.android.email.Email;
|
||||||
|
import com.android.email.R;
|
||||||
import com.android.email.RefreshManager;
|
import com.android.email.RefreshManager;
|
||||||
|
import com.android.email.activity.setup.AccountSettingsXL;
|
||||||
import com.android.emailcommon.Logging;
|
import com.android.emailcommon.Logging;
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
import com.android.emailcommon.provider.EmailContent.Account;
|
||||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
|
import android.app.FragmentManager;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -35,11 +38,16 @@ import java.util.ArrayList;
|
||||||
/**
|
/**
|
||||||
* Base class for the UI controller.
|
* Base class for the UI controller.
|
||||||
*
|
*
|
||||||
* Note: Always use {@link #commitFragmentTransaction} to commit fragment transactions.
|
* Note: Always use {@link #commitFragmentTransaction} and {@link #popBackStack} to operate fragment
|
||||||
|
* transactions.
|
||||||
* (Currently we use synchronous transactions only, but we may want to switch back to asynchronous
|
* (Currently we use synchronous transactions only, but we may want to switch back to asynchronous
|
||||||
* later.)
|
* later.)
|
||||||
*/
|
*/
|
||||||
abstract class UIControllerBase {
|
abstract class UIControllerBase {
|
||||||
|
protected static final String BUNDLE_KEY_ACCOUNT_ID = "UIController.state.account_id";
|
||||||
|
protected static final String BUNDLE_KEY_MAILBOX_ID = "UIController.state.mailbox_id";
|
||||||
|
protected static final String BUNDLE_KEY_MESSAGE_ID = "UIController.state.message_id";
|
||||||
|
|
||||||
/** No account selected */
|
/** No account selected */
|
||||||
static final long NO_ACCOUNT = -1;
|
static final long NO_ACCOUNT = -1;
|
||||||
/** No mailbox selected */
|
/** No mailbox selected */
|
||||||
|
@ -50,10 +58,10 @@ abstract class UIControllerBase {
|
||||||
/** The owner activity */
|
/** The owner activity */
|
||||||
final EmailActivity mActivity;
|
final EmailActivity mActivity;
|
||||||
|
|
||||||
final RefreshManager mRefreshManager;
|
|
||||||
|
|
||||||
final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||||
|
|
||||||
|
final RefreshManager mRefreshManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of fragments that are restored by the framework while the activity is being re-created
|
* List of fragments that are restored by the framework while the activity is being re-created
|
||||||
* for configuration changes (e.g. screen rotation). We'll install them later when the activity
|
* for configuration changes (e.g. screen rotation). We'll install them later when the activity
|
||||||
|
@ -67,6 +75,19 @@ abstract class UIControllerBase {
|
||||||
*/
|
*/
|
||||||
private boolean mHoldFragmentInstallation = true;
|
private boolean mHoldFragmentInstallation = true;
|
||||||
|
|
||||||
|
private final RefreshManager.Listener mRefreshListener
|
||||||
|
= new RefreshManager.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onMessagingError(final long accountId, long mailboxId, final String message) {
|
||||||
|
updateRefreshProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefreshStatusChanged(long accountId, long mailboxId) {
|
||||||
|
updateRefreshProgress();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public UIControllerBase(EmailActivity activity) {
|
public UIControllerBase(EmailActivity activity) {
|
||||||
mActivity = activity;
|
mActivity = activity;
|
||||||
mRefreshManager = RefreshManager.getInstance(mActivity);
|
mRefreshManager = RefreshManager.getInstance(mActivity);
|
||||||
|
@ -101,6 +122,7 @@ abstract class UIControllerBase {
|
||||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||||
Log.d(Logging.LOG_TAG, this + " onActivityCreated");
|
Log.d(Logging.LOG_TAG, this + " onActivityCreated");
|
||||||
}
|
}
|
||||||
|
mRefreshManager.registerListener(mRefreshListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,6 +169,7 @@ abstract class UIControllerBase {
|
||||||
Log.d(Logging.LOG_TAG, this + " onActivityDestroy");
|
Log.d(Logging.LOG_TAG, this + " onActivityDestroy");
|
||||||
}
|
}
|
||||||
mHoldFragmentInstallation = true; // No more fragment installation.
|
mHoldFragmentInstallation = true; // No more fragment installation.
|
||||||
|
mRefreshManager.unregisterListener(mRefreshListener);
|
||||||
mTaskTracker.cancellAllInterrupt();
|
mTaskTracker.cancellAllInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,6 +232,11 @@ abstract class UIControllerBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not used
|
||||||
|
void popBackStack(FragmentManager fm, String name, int flags) {
|
||||||
|
fm.popBackStackImmediate(name, flags);
|
||||||
|
}
|
||||||
|
|
||||||
void commitFragmentTransaction(FragmentTransaction ft) {
|
void commitFragmentTransaction(FragmentTransaction ft) {
|
||||||
ft.commit();
|
ft.commit();
|
||||||
mActivity.getFragmentManager().executePendingTransactions();
|
mActivity.getFragmentManager().executePendingTransactions();
|
||||||
|
@ -222,15 +250,29 @@ abstract class UIControllerBase {
|
||||||
*/
|
*/
|
||||||
public abstract long getUIAccountId();
|
public abstract long getUIAccountId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if an account is selected, or the current view is the combined view.
|
||||||
|
*/
|
||||||
|
public final boolean isAccountSelected() {
|
||||||
|
return getUIAccountId() != NO_ACCOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return if an actual account is selected. (i.e. {@link Account#ACCOUNT_ID_COMBINED_VIEW}
|
||||||
|
* is not considered "actual".s)
|
||||||
|
*/
|
||||||
|
public final boolean isActualAccountSelected() {
|
||||||
|
return isAccountSelected() && (getUIAccountId() != Account.ACCOUNT_ID_COMBINED_VIEW);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the currently selected account ID. If the current view is the combined view,
|
* @return the currently selected account ID. If the current view is the combined view,
|
||||||
* it'll return {@link #NO_ACCOUNT}.
|
* it'll return {@link #NO_ACCOUNT}.
|
||||||
*
|
*
|
||||||
* @see #getUIAccountId()
|
* @see #getUIAccountId()
|
||||||
*/
|
*/
|
||||||
public long getActualAccountId() {
|
public final long getActualAccountId() {
|
||||||
final long uiAccountId = getUIAccountId();
|
return isActualAccountSelected() ? getUIAccountId() : NO_ACCOUNT;
|
||||||
return uiAccountId == Account.ACCOUNT_ID_COMBINED_VIEW ? NO_ACCOUNT : uiAccountId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,19 +305,71 @@ abstract class UIControllerBase {
|
||||||
/**
|
/**
|
||||||
* Handles the {@link android.app.Activity#onCreateOptionsMenu} callback.
|
* Handles the {@link android.app.Activity#onCreateOptionsMenu} callback.
|
||||||
*/
|
*/
|
||||||
public abstract boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu);
|
public boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
|
||||||
|
inflater.inflate(R.menu.email_activity_options, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the {@link android.app.Activity#onPrepareOptionsMenu} callback.
|
* Handles the {@link android.app.Activity#onPrepareOptionsMenu} callback.
|
||||||
*/
|
*/
|
||||||
public abstract boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu);
|
public boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu) {
|
||||||
|
|
||||||
|
// Update the refresh button.
|
||||||
|
MenuItem item = menu.findItem(R.id.refresh);
|
||||||
|
if (isRefreshEnabled()) {
|
||||||
|
item.setVisible(true);
|
||||||
|
if (isRefreshInProgress()) {
|
||||||
|
item.setActionView(R.layout.action_bar_indeterminate_progress);
|
||||||
|
} else {
|
||||||
|
item.setActionView(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item.setVisible(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the {@link android.app.Activity#onOptionsItemSelected} callback.
|
* Handles the {@link android.app.Activity#onOptionsItemSelected} callback.
|
||||||
*
|
*
|
||||||
* @return true if the option item is handled.
|
* @return true if the option item is handled.
|
||||||
*/
|
*/
|
||||||
public abstract boolean onOptionsItemSelected(MenuItem item);
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
// Comes from the action bar when the app icon on the left is pressed.
|
||||||
|
// It works like a back press, but it won't close the activity.
|
||||||
|
return onBackPressed(false);
|
||||||
|
case R.id.compose:
|
||||||
|
return onCompose();
|
||||||
|
case R.id.refresh:
|
||||||
|
onRefresh();
|
||||||
|
return true;
|
||||||
|
case R.id.account_settings:
|
||||||
|
return onAccountSettings();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the message compose activity.
|
||||||
|
*/
|
||||||
|
private boolean onCompose() {
|
||||||
|
if (!isAccountSelected()) {
|
||||||
|
return false; // this shouldn't really happen
|
||||||
|
}
|
||||||
|
MessageCompose.actionCompose(mActivity, getActualAccountId());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the "Settings" option item. Opens the settings activity.
|
||||||
|
*/
|
||||||
|
private boolean onAccountSettings() {
|
||||||
|
AccountSettingsXL.actionSettings(mActivity, getActualAccountId());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STOPSHIP For experimental UI. Remove this.
|
* STOPSHIP For experimental UI. Remove this.
|
||||||
|
@ -292,10 +386,30 @@ abstract class UIControllerBase {
|
||||||
public abstract long getMailboxSettingsMailboxId();
|
public abstract long getMailboxSettingsMailboxId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* STOPSHIP For experimental UI. Remove this.
|
* STOPSHIP For experimental UI. Make it abstract protected.
|
||||||
*
|
*
|
||||||
* Performs "refesh".
|
* Performs "refesh".
|
||||||
*/
|
*/
|
||||||
public void onRefresh() {
|
public abstract void onRefresh();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if refresh is in progress for the current mailbox.
|
||||||
|
*/
|
||||||
|
protected abstract boolean isRefreshInProgress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the UI should enable the "refresh" command.
|
||||||
|
*/
|
||||||
|
protected abstract boolean isRefreshEnabled();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start/stop the "refresh" animation on the action bar according to the current refresh state.
|
||||||
|
*
|
||||||
|
* (We start the animation if {@link #isRefreshInProgress} returns true,
|
||||||
|
* and stop otherwise.)
|
||||||
|
*/
|
||||||
|
protected void updateRefreshProgress() {
|
||||||
|
mActivity.invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,57 +16,391 @@
|
||||||
|
|
||||||
package com.android.email.activity;
|
package com.android.email.activity;
|
||||||
|
|
||||||
|
import com.android.email.Email;
|
||||||
import com.android.email.R;
|
import com.android.email.R;
|
||||||
|
import com.android.emailcommon.Logging;
|
||||||
|
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
||||||
|
import com.android.emailcommon.utility.Utility;
|
||||||
|
|
||||||
import android.view.Menu;
|
import android.app.Fragment;
|
||||||
import android.view.MenuInflater;
|
import android.app.FragmentManager;
|
||||||
import android.view.MenuItem;
|
import android.app.FragmentTransaction;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI Controller for non x-large devices. Supports a single-pane layout.
|
* UI Controller for non x-large devices. Supports a single-pane layout.
|
||||||
|
*
|
||||||
|
* STOPSHIP Everything in this class is 100% temporary at this point
|
||||||
|
* - Navigation model is different from what it should be (whatever it'll be).
|
||||||
|
* e.g. when the app is launched, we should show Inbox, not mailbox list.
|
||||||
|
*
|
||||||
|
* - It uses the two-pane action bar only so that we can change accounts
|
||||||
|
*
|
||||||
|
* Major TODOs
|
||||||
|
* - TODO Proper Navigation model, including retaining fragments to keep state such as the scroll
|
||||||
|
* position and batch selection.
|
||||||
|
* - TODO Nested folders
|
||||||
|
* - TODO Newer/Older for message view
|
||||||
|
* - TODO Implement callbacks
|
||||||
*/
|
*/
|
||||||
class UIControllerOnePane extends UIControllerBase {
|
class UIControllerOnePane extends UIControllerBase {
|
||||||
|
private ActionBarController mActionBarController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current account/mailbox/message IDs.
|
||||||
|
* Don't use them directly; use the accessors instead, as we might want to get them from the
|
||||||
|
* topmost fragment in the future.
|
||||||
|
*/
|
||||||
|
private long mCurrentAccountId = NO_ACCOUNT;
|
||||||
|
private long mCurrentMailboxId = NO_MAILBOX;
|
||||||
|
private long mCurrentMessageId = NO_MESSAGE;
|
||||||
|
|
||||||
|
private MessageCommandButtonView mMessageCommandButtons;
|
||||||
|
|
||||||
|
private final MailboxListFragment.Callback mMailboxListFragmentCallback =
|
||||||
|
new MailboxListFragment.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onAccountSelected(long accountId) {
|
||||||
|
openAccount(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCurrentMailboxUpdated(long mailboxId, String mailboxName, int unreadCount) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMailboxSelected(
|
||||||
|
long accountId, long mailboxId, boolean navigate, boolean dragDrop) {
|
||||||
|
open(accountId, mailboxId, NO_MESSAGE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final MessageListFragment.Callback mMessageListFragmentCallback =
|
||||||
|
new MessageListFragment.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onAdvancingOpAccepted(Set<Long> affectedMessages) {
|
||||||
|
// Nothing to do on 1 pane.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnterSelectionMode(boolean enter) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListLoaded() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMailboxNotFound() {
|
||||||
|
open(getUIAccountId(), NO_MAILBOX, NO_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageOpen(
|
||||||
|
long messageId, long messageMailboxId, long listMailboxId, int type) {
|
||||||
|
if (type == MessageListFragment.Callback.TYPE_DRAFT) {
|
||||||
|
MessageCompose.actionEditDraft(mActivity, messageId);
|
||||||
|
} else {
|
||||||
|
open(getUIAccountId(), getMailboxId(), messageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final MessageViewFragment.Callback mMessageViewFragmentCallback =
|
||||||
|
new MessageViewFragment.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onForward() {
|
||||||
|
MessageCompose.actionForward(mActivity, getMessageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReply() {
|
||||||
|
MessageCompose.actionReply(mActivity, getMessageId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReplyAll() {
|
||||||
|
MessageCompose.actionReply(mActivity, getMessageId(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCalendarLinkClicked(long epochEventStartTime) {
|
||||||
|
ActivityHelper.openCalendar(mActivity, epochEventStartTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onUrlInMessageClicked(String url) {
|
||||||
|
return ActivityHelper.openUrlInMessage(mActivity, url, getActualAccountId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBeforeMessageGone() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageSetUnread() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRespondedToInvite(int response) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMessageError(String errorMessage) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMessageFinished() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadMessageStarted() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageNotExists() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageViewGone() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageViewShown(int mailboxType) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// This is all temporary as we'll have a different action bar controller for 1-pane.
|
||||||
|
private final ActionBarController.Callback mActionBarControllerCallback
|
||||||
|
= new ActionBarController.Callback() {
|
||||||
|
@Override
|
||||||
|
public boolean shouldShowMailboxName() {
|
||||||
|
return false; // no mailbox name/unread count.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getCurrentMailboxName() {
|
||||||
|
return null; // no mailbox name/unread count.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCurrentMailboxUnreadCount() {
|
||||||
|
return 0; // no mailbox name/unread count.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldShowUp() {
|
||||||
|
// Always show the UP arrow.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getUIAccountId() {
|
||||||
|
return UIControllerOnePane.this.getUIAccountId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountSelected() {
|
||||||
|
return UIControllerOnePane.this.isAccountSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccountSelected(long accountId) {
|
||||||
|
openAccount(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNoAccountsFound() {
|
||||||
|
Welcome.actionStart(mActivity);
|
||||||
|
mActivity.finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public UIControllerOnePane(EmailActivity activity) {
|
public UIControllerOnePane(EmailActivity activity) {
|
||||||
super(activity);
|
super(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
outState.putLong(BUNDLE_KEY_ACCOUNT_ID, mCurrentAccountId);
|
||||||
|
outState.putLong(BUNDLE_KEY_MAILBOX_ID, mCurrentMailboxId);
|
||||||
|
outState.putLong(BUNDLE_KEY_MESSAGE_ID, mCurrentMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreInstanceState(Bundle savedInstanceState) {
|
||||||
|
super.restoreInstanceState(savedInstanceState);
|
||||||
|
mCurrentAccountId = savedInstanceState.getLong(BUNDLE_KEY_ACCOUNT_ID, NO_ACCOUNT);
|
||||||
|
mCurrentMailboxId = savedInstanceState.getLong(BUNDLE_KEY_MAILBOX_ID, NO_MAILBOX);
|
||||||
|
mCurrentMessageId = savedInstanceState.getLong(BUNDLE_KEY_MESSAGE_ID, NO_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getLayoutId() {
|
public int getLayoutId() {
|
||||||
return R.layout.email_activity_one_pane;
|
return R.layout.email_activity_one_pane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityViewReady() {
|
||||||
|
super.onActivityViewReady();
|
||||||
|
mActionBarController = new ActionBarController(mActivity, mActivity.getLoaderManager(),
|
||||||
|
mActivity.getActionBar(), mActionBarControllerCallback);
|
||||||
|
|
||||||
|
mMessageCommandButtons = UiUtilities.getView(mActivity, R.id.message_command_buttons);
|
||||||
|
mMessageCommandButtons.setCallback(new CommandButtonCallback());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityCreated() {
|
||||||
|
super.onActivityCreated();
|
||||||
|
mActionBarController.onActivityCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResume() {
|
||||||
|
super.onActivityResume();
|
||||||
|
refreshActionBar();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getUIAccountId() {
|
public long getUIAccountId() {
|
||||||
return -1;
|
return mCurrentAccountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getMailboxId() {
|
||||||
|
return mCurrentMailboxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getMessageId() {
|
||||||
|
return mCurrentMessageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshActionBar() {
|
||||||
|
if (mActionBarController != null) {
|
||||||
|
mActionBarController.refresh();
|
||||||
|
}
|
||||||
|
mActivity.invalidateOptionsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMailboxListVisible() {
|
||||||
|
return (getMailboxId() == NO_MAILBOX);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMessageListVisible() {
|
||||||
|
return (getMailboxId() != NO_MAILBOX) && (getMessageId() == NO_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMessageViewVisible() {
|
||||||
|
return (getMailboxId() != NO_MAILBOX) && (getMessageId() != NO_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onBackPressed(boolean isSystemBackKey) {
|
public boolean onBackPressed(boolean isSystemBackKey) {
|
||||||
return false;
|
if (isMessageViewVisible()) {
|
||||||
|
open(getUIAccountId(), getMailboxId(), NO_MESSAGE);
|
||||||
|
return true;
|
||||||
|
} else if (isMessageListVisible()) {
|
||||||
|
open(getUIAccountId(), NO_MAILBOX, NO_MESSAGE);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// STOPSHIP Remove this and return false. This is so that the app can be closed
|
||||||
|
// with the UP press. (usuful when the device doesn't have a HW back key.)
|
||||||
|
mActivity.finish();
|
||||||
|
return true;
|
||||||
|
// return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
|
void installFragment(Fragment fragment) {
|
||||||
return false;
|
super.installFragment(fragment);
|
||||||
}
|
if (fragment instanceof MailboxListFragment) {
|
||||||
|
((MailboxListFragment) fragment).setCallback(mMailboxListFragmentCallback);
|
||||||
@Override
|
} else if (fragment instanceof MessageListFragment) {
|
||||||
public boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu) {
|
((MessageListFragment) fragment).setCallback(mMessageListFragmentCallback);
|
||||||
return false;
|
} else if (fragment instanceof MessageViewFragment) {
|
||||||
}
|
((MessageViewFragment) fragment).setCallback(mMessageViewFragmentCallback);
|
||||||
|
} else {
|
||||||
@Override
|
// Ignore -- uninteresting fragments such as dialogs.
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void open(long accountId, long mailboxId, long messageId) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openAccount(long accountId) {
|
public void openAccount(long accountId) {
|
||||||
|
open(accountId, NO_MAILBOX, NO_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void open(final long accountId, final long mailboxId, final long messageId) {
|
||||||
|
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
||||||
|
Log.d(Logging.LOG_TAG, this + " open accountId=" + accountId
|
||||||
|
+ " mailboxId=" + mailboxId + " messageId=" + messageId);
|
||||||
|
}
|
||||||
|
if (accountId == NO_ACCOUNT) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// !!! It's all temporary to make 1 pane UI (barely) usable !!!
|
||||||
|
//
|
||||||
|
// - Nested folders still doesn't work
|
||||||
|
// - When opening a child view (e.g. message list -> message view), we should retain
|
||||||
|
// the current fragment so that all the state (selection, scroll position, etc) will be
|
||||||
|
// restored when back.
|
||||||
|
|
||||||
|
if ((getUIAccountId() == accountId) && (getMailboxId() == mailboxId)
|
||||||
|
&& (getMessageId() == messageId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FragmentManager fm = mActivity.getFragmentManager();
|
||||||
|
final FragmentTransaction ft = fm.beginTransaction();
|
||||||
|
|
||||||
|
if (messageId != NO_MESSAGE) {
|
||||||
|
ft.replace(R.id.fragment_placeholder, MessageViewFragment.newInstance(messageId));
|
||||||
|
|
||||||
|
} else if (mailboxId != NO_MAILBOX) {
|
||||||
|
ft.replace(R.id.fragment_placeholder, MessageListFragment.newInstance(mailboxId));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ft.replace(R.id.fragment_placeholder,
|
||||||
|
MailboxListFragment.newInstance(accountId, Mailbox.PARENT_KEY_NONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentAccountId = accountId;
|
||||||
|
mCurrentMailboxId = mailboxId;
|
||||||
|
mCurrentMessageId = messageId;
|
||||||
|
|
||||||
|
commitFragmentTransaction(ft);
|
||||||
|
|
||||||
|
refreshActionBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -74,7 +408,8 @@ class UIControllerOnePane extends UIControllerBase {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public long getMailboxSettingsMailboxId() {
|
public long getMailboxSettingsMailboxId() {
|
||||||
// Mailbox settigns is still experimental, and doesn't have to work on the phone.
|
// Mailbox settings is still experimental, and doesn't have to work on the phone.
|
||||||
|
Utility.showToast(mActivity, "STOPSHIP: Mailbox settings not supported on 1 pane");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +419,51 @@ class UIControllerOnePane extends UIControllerBase {
|
||||||
@Override
|
@Override
|
||||||
public long getSearchMailboxId() {
|
public long getSearchMailboxId() {
|
||||||
// Search is still experimental, and doesn't have to work on the phone.
|
// Search is still experimental, and doesn't have to work on the phone.
|
||||||
|
Utility.showToast(mActivity, "STOPSHIP: Search not supported on 1 pane");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class CommandButtonCallback implements MessageCommandButtonView.Callback {
|
||||||
|
@Override
|
||||||
|
public void onMoveToNewer() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMoveToOlder() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isRefreshEnabled() {
|
||||||
|
// Refreshable only when an actual account is selected, and message view isn't shown.
|
||||||
|
// (i.e. only available on the mailbox list or the message view, but not on the combined
|
||||||
|
// one)
|
||||||
|
return isActualAccountSelected() && !isMessageViewVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
if (!isRefreshEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isMessageListVisible()) {
|
||||||
|
mRefreshManager.refreshMessageList(getActualAccountId(), getMailboxId(), true);
|
||||||
|
} else {
|
||||||
|
mRefreshManager.refreshMailboxList(getActualAccountId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isRefreshInProgress() {
|
||||||
|
if (!isRefreshEnabled()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isMessageListVisible()) {
|
||||||
|
return mRefreshManager.isMessageListRefreshing(getMailboxId());
|
||||||
|
} else {
|
||||||
|
return mRefreshManager.isMailboxListRefreshing(getActualAccountId());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@ import com.android.email.Preferences;
|
||||||
import com.android.email.R;
|
import com.android.email.R;
|
||||||
import com.android.email.RefreshManager;
|
import com.android.email.RefreshManager;
|
||||||
import com.android.email.activity.setup.AccountSecurity;
|
import com.android.email.activity.setup.AccountSecurity;
|
||||||
import com.android.email.activity.setup.AccountSettingsXL;
|
|
||||||
import com.android.emailcommon.Logging;
|
import com.android.emailcommon.Logging;
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
import com.android.emailcommon.provider.EmailContent.Account;
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
||||||
|
@ -36,9 +35,6 @@ import android.app.FragmentTransaction;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -53,9 +49,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
MailboxListFragment.Callback,
|
MailboxListFragment.Callback,
|
||||||
MessageListFragment.Callback,
|
MessageListFragment.Callback,
|
||||||
MessageViewFragment.Callback {
|
MessageViewFragment.Callback {
|
||||||
private static final String BUNDLE_KEY_ACCOUNT_ID = "UIControllerTwoPane.state.account_id";
|
|
||||||
private static final String BUNDLE_KEY_MAILBOX_ID = "UIControllerTwoPane.state.mailbox_id";
|
|
||||||
private static final String BUNDLE_KEY_MESSAGE_ID = "UIControllerTwoPane.state.message_id";
|
|
||||||
private static final String BUNDLE_KEY_MAILBOX_STACK
|
private static final String BUNDLE_KEY_MAILBOX_STACK
|
||||||
= "UIControllerTwoPane.state.mailbox_stack";
|
= "UIControllerTwoPane.state.mailbox_stack";
|
||||||
|
|
||||||
|
@ -102,7 +95,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
|
|
||||||
private MailboxFinder mMailboxFinder;
|
private MailboxFinder mMailboxFinder;
|
||||||
|
|
||||||
private final RefreshListener mRefreshListener = new RefreshListener();
|
|
||||||
private MessageOrderManager mOrderManager;
|
private MessageOrderManager mOrderManager;
|
||||||
private final MessageOrderManagerCallback mMessageOrderManagerCallback =
|
private final MessageOrderManagerCallback mMessageOrderManagerCallback =
|
||||||
new MessageOrderManagerCallback();
|
new MessageOrderManagerCallback();
|
||||||
|
@ -383,9 +375,7 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onActivityViewReady() {
|
public void onActivityViewReady() {
|
||||||
if (Email.DEBUG_LIFECYCLE && Email.DEBUG) {
|
super.onActivityViewReady();
|
||||||
Log.d(Logging.LOG_TAG, this + " onActivityViewReady");
|
|
||||||
}
|
|
||||||
mActionBarController = new ActionBarController(mActivity, mActivity.getLoaderManager(),
|
mActionBarController = new ActionBarController(mActivity, mActivity.getLoaderManager(),
|
||||||
mActivity.getActionBar(), mActionBarControllerCallback);
|
mActivity.getActionBar(), mActionBarControllerCallback);
|
||||||
|
|
||||||
|
@ -407,17 +397,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
return mAccountId;
|
return mAccountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the currently selected account ID. If the current view is the combined view,
|
|
||||||
* it'll return {@link #NO_ACCOUNT}.
|
|
||||||
*
|
|
||||||
* @see #getUIAccountId()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public long getActualAccountId() {
|
|
||||||
return mAccountId == Account.ACCOUNT_ID_COMBINED_VIEW ? NO_ACCOUNT : mAccountId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the id of the mailbox used for the message list fragment.
|
* Returns the id of the mailbox used for the message list fragment.
|
||||||
* IMPORTANT: Do not confuse this with {@link #mMailboxListMailboxId} which is the id used
|
* IMPORTANT: Do not confuse this with {@link #mMailboxListMailboxId} which is the id used
|
||||||
|
@ -449,25 +428,19 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
return mMessageId;
|
return mMessageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean isMailboxSelected() {
|
||||||
* @return true if an account is selected, or the current view is the combined view.
|
|
||||||
*/
|
|
||||||
public boolean isAccountSelected() {
|
|
||||||
return getUIAccountId() != NO_ACCOUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMailboxSelected() {
|
|
||||||
return getMessageListMailboxId() != NO_MAILBOX;
|
return getMessageListMailboxId() != NO_MAILBOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMessageSelected() {
|
private boolean isMessageSelected() {
|
||||||
return getMessageId() != NO_MESSAGE;
|
return getMessageId() != NO_MESSAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if refresh is in progress for the current mailbox.
|
* @return true if refresh is in progress for the current mailbox.
|
||||||
*/
|
*/
|
||||||
public boolean isRefreshInProgress() {
|
@Override
|
||||||
|
protected boolean isRefreshInProgress() {
|
||||||
long messageListMailboxId = getMessageListMailboxId();
|
long messageListMailboxId = getMessageListMailboxId();
|
||||||
return (messageListMailboxId >= 0)
|
return (messageListMailboxId >= 0)
|
||||||
&& mRefreshManager.isMessageListRefreshing(messageListMailboxId);
|
&& mRefreshManager.isMessageListRefreshing(messageListMailboxId);
|
||||||
|
@ -476,7 +449,8 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
/**
|
/**
|
||||||
* @return true if the UI should enable the "refresh" command.
|
* @return true if the UI should enable the "refresh" command.
|
||||||
*/
|
*/
|
||||||
public boolean isRefreshEnabled() {
|
@Override
|
||||||
|
protected boolean isRefreshEnabled() {
|
||||||
// - Don't show for combined inboxes, but
|
// - Don't show for combined inboxes, but
|
||||||
// - Show even for non-refreshable mailboxes, in which case we refresh the mailbox list
|
// - Show even for non-refreshable mailboxes, in which case we refresh the mailbox list
|
||||||
return -1 != getActualAccountId();
|
return -1 != getActualAccountId();
|
||||||
|
@ -488,7 +462,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
@Override
|
@Override
|
||||||
public void onActivityCreated() {
|
public void onActivityCreated() {
|
||||||
super.onActivityCreated();
|
super.onActivityCreated();
|
||||||
mRefreshManager.registerListener(mRefreshListener);
|
|
||||||
mActionBarController.onActivityCreated();
|
mActionBarController.onActivityCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +498,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
@Override
|
@Override
|
||||||
public void onActivityDestroy() {
|
public void onActivityDestroy() {
|
||||||
closeMailboxFinder();
|
closeMailboxFinder();
|
||||||
mRefreshManager.unregisterListener(mRefreshListener);
|
|
||||||
super.onActivityDestroy();
|
super.onActivityDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,43 +896,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles {@link android.app.Activity#onCreateOptionsMenu} callback.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean onCreateOptionsMenu(MenuInflater inflater, Menu menu) {
|
|
||||||
inflater.inflate(R.menu.email_activity_options, menu);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public boolean onPrepareOptionsMenu(MenuInflater inflater, Menu menu) {
|
|
||||||
ActivityHelper.updateRefreshMenuIcon(menu.findItem(R.id.refresh),
|
|
||||||
isRefreshEnabled(),
|
|
||||||
isRefreshInProgress());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
// Comes from the action bar when the app icon on the left is pressed.
|
|
||||||
// It works like a back press, but it won't close the activity.
|
|
||||||
return onBackPressed(false);
|
|
||||||
case R.id.compose:
|
|
||||||
return onCompose();
|
|
||||||
case R.id.refresh:
|
|
||||||
onRefresh();
|
|
||||||
return true;
|
|
||||||
case R.id.account_settings:
|
|
||||||
return onAccountSettings();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean onBackPressed(boolean isSystemBackKey) {
|
public boolean onBackPressed(boolean isSystemBackKey) {
|
||||||
|
@ -979,25 +914,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the "Compose" option item. Opens the message compose activity.
|
|
||||||
*/
|
|
||||||
private boolean onCompose() {
|
|
||||||
if (!isAccountSelected()) {
|
|
||||||
return false; // this shouldn't really happen
|
|
||||||
}
|
|
||||||
MessageCompose.actionCompose(mActivity, getActualAccountId());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the "Compose" option item. Opens the settings activity.
|
|
||||||
*/
|
|
||||||
private boolean onAccountSettings() {
|
|
||||||
AccountSettingsXL.actionSettings(mActivity, getActualAccountId());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the "refresh" option item. Opens the settings activity.
|
* Handles the "refresh" option item. Opens the settings activity.
|
||||||
* TODO used by experimental code in the activity -- otherwise can be private.
|
* TODO used by experimental code in the activity -- otherwise can be private.
|
||||||
|
@ -1009,29 +925,6 @@ class UIControllerTwoPane extends UIControllerBase implements
|
||||||
getMessageListMailboxId()).cancelPreviousAndExecuteParallel();
|
getMessageListMailboxId()).cancelPreviousAndExecuteParallel();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Start/stop the "refresh" animation on the action bar according to the current refresh state.
|
|
||||||
*
|
|
||||||
* (We start the animation if {@link UIControllerTwoPane#isRefreshInProgress} returns true,
|
|
||||||
* and stop otherwise.)
|
|
||||||
*/
|
|
||||||
private void updateRefreshProgress() {
|
|
||||||
mActivity.invalidateOptionsMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RefreshListener
|
|
||||||
implements RefreshManager.Listener {
|
|
||||||
@Override
|
|
||||||
public void onMessagingError(final long accountId, long mailboxId, final String message) {
|
|
||||||
updateRefreshProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRefreshStatusChanged(long accountId, long mailboxId) {
|
|
||||||
updateRefreshProgress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to handle refresh.
|
* Class to handle refresh.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,14 +23,12 @@ import com.android.email.provider.AccountBackupRestore;
|
||||||
import com.android.email.service.MailService;
|
import com.android.email.service.MailService;
|
||||||
import com.android.emailcommon.provider.EmailContent;
|
import com.android.emailcommon.provider.EmailContent;
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
import com.android.emailcommon.provider.EmailContent.Account;
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
import com.android.emailcommon.utility.EmailAsyncTask;
|
import com.android.emailcommon.utility.EmailAsyncTask;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -77,16 +75,6 @@ public class Welcome extends Activity {
|
||||||
|
|
||||||
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
private final EmailAsyncTask.Tracker mTaskTracker = new EmailAsyncTask.Tracker();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the obsolete phone UI should be used.
|
|
||||||
*
|
|
||||||
* STOPSHIP remove this. temporary support for the old activities.
|
|
||||||
*/
|
|
||||||
public static boolean useOldPhoneActivities(Context context) {
|
|
||||||
final int screenLayout = context.getResources().getConfiguration().screenLayout;
|
|
||||||
return (screenLayout & Configuration.SCREENLAYOUT_SIZE_XLARGE) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch this activity. Note: It's assumed that this activity is only called as a means to
|
* Launch this activity. Note: It's assumed that this activity is only called as a means to
|
||||||
* 'reset' the UI state; Because of this, it is always launched with FLAG_ACTIVITY_CLEAR_TOP,
|
* 'reset' the UI state; Because of this, it is always launched with FLAG_ACTIVITY_CLEAR_TOP,
|
||||||
|
@ -244,39 +232,20 @@ public class Welcome extends Activity {
|
||||||
} else {
|
} else {
|
||||||
final long accountId = resolveAccountId(mFromActivity, mAccountId, mAccountUuid);
|
final long accountId = resolveAccountId(mFromActivity, mAccountId, mAccountUuid);
|
||||||
|
|
||||||
// Use the old phone activities on x-large devices, only when the debug pane mode
|
final Intent i;
|
||||||
// is not specified.
|
if (isMessageSelected()) {
|
||||||
// If the debug pane mode is specified, always use EmailActivity.
|
i = EmailActivity.createOpenMessageIntent(mFromActivity, accountId,
|
||||||
// STOPSHIP remove this. temporary support for the old activities.
|
mMailboxId, mMessageId);
|
||||||
final boolean useOldPhoneActivities = mDebugPaneMode == 0
|
} else if (isMailboxSelected()) {
|
||||||
&& useOldPhoneActivities(mFromActivity);
|
i = EmailActivity.createOpenMailboxIntent(mFromActivity, accountId,
|
||||||
|
mMailboxId);
|
||||||
if (!useOldPhoneActivities) {
|
|
||||||
final Intent i;
|
|
||||||
if (isMessageSelected()) {
|
|
||||||
i = EmailActivity.createOpenMessageIntent(mFromActivity, accountId,
|
|
||||||
mMailboxId, mMessageId);
|
|
||||||
} else if (isMailboxSelected()) {
|
|
||||||
i = EmailActivity.createOpenMailboxIntent(mFromActivity, accountId,
|
|
||||||
mMailboxId);
|
|
||||||
} else {
|
|
||||||
i = EmailActivity.createOpenAccountIntent(mFromActivity, accountId);
|
|
||||||
}
|
|
||||||
if (mDebugPaneMode != 0) {
|
|
||||||
EmailActivity.forcePaneMode(i, mDebugPaneMode == 2);
|
|
||||||
}
|
|
||||||
mFromActivity.startActivity(i);
|
|
||||||
} else {
|
} else {
|
||||||
// STOPSHIP remove this. temporary support for the old activities.
|
i = EmailActivity.createOpenAccountIntent(mFromActivity, accountId);
|
||||||
if (isMessageSelected()) {
|
|
||||||
MessageView.actionView(mFromActivity, mMessageId, mMailboxId);
|
|
||||||
} else if (isMailboxSelected()) {
|
|
||||||
MessageList.actionHandleMailbox(mFromActivity, mMailboxId);
|
|
||||||
} else {
|
|
||||||
MessageList.actionHandleAccount(
|
|
||||||
mFromActivity, accountId, Mailbox.TYPE_INBOX);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (mDebugPaneMode != 0) {
|
||||||
|
EmailActivity.forcePaneMode(i, mDebugPaneMode == 2);
|
||||||
|
}
|
||||||
|
mFromActivity.startActivity(i);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,278 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Account;
|
|
||||||
import com.android.emailcommon.provider.EmailContent.Mailbox;
|
|
||||||
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.database.MatrixCursor;
|
|
||||||
import android.database.MergeCursor;
|
|
||||||
import android.database.MatrixCursor.RowBuilder;
|
|
||||||
import android.test.AndroidTestCase;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic unit tests of AccountsAdapter
|
|
||||||
*/
|
|
||||||
@SmallTest
|
|
||||||
public class AccountsAdapterTest extends AndroidTestCase {
|
|
||||||
|
|
||||||
private Cursor mUpperCursor = null;
|
|
||||||
private Cursor mLowerCursor = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an empty set of magic mailboxes in mUpperCursor
|
|
||||||
*/
|
|
||||||
private void setupUpperCursor() {
|
|
||||||
MatrixCursor childCursor = new MatrixCursor(AccountsAdapter.MAILBOX_PROJECTION);
|
|
||||||
mUpperCursor = childCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a simple set of magic mailboxes in mUpperCursor
|
|
||||||
*/
|
|
||||||
private void populateUpperCursor() {
|
|
||||||
MatrixCursor childCursor = (MatrixCursor) mUpperCursor;
|
|
||||||
|
|
||||||
int count;
|
|
||||||
RowBuilder row;
|
|
||||||
// TYPE_INBOX
|
|
||||||
count = 10;
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_INBOXES)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
row.add("Inbox"); // MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_INBOX)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
// TYPE_MAIL (FAVORITES)
|
|
||||||
count = 20;
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_FAVORITES)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
row.add("Favorites"); // MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_MAIL)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
// TYPE_DRAFTS
|
|
||||||
count = 30;
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_DRAFTS)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
row.add("Drafts"); // MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_DRAFTS)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
// TYPE_OUTBOX
|
|
||||||
count = 40;
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(Mailbox.QUERY_ALL_OUTBOX)); // MAILBOX_COLUMN_ID = 0;
|
|
||||||
row.add("Outbox"); // MAILBOX_DISPLAY_NAME
|
|
||||||
row.add(null); // MAILBOX_ACCOUNT_KEY = 2;
|
|
||||||
row.add(Integer.valueOf(Mailbox.TYPE_OUTBOX)); // MAILBOX_TYPE = 3;
|
|
||||||
row.add(Integer.valueOf(count)); // MAILBOX_UNREAD_COUNT = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an empty set of accounts in mLowerCursor
|
|
||||||
*/
|
|
||||||
private void setupLowerCursor() {
|
|
||||||
MatrixCursor childCursor = new MatrixCursor(Account.CONTENT_PROJECTION);
|
|
||||||
mLowerCursor = childCursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make a simple set of "accounts".
|
|
||||||
* Note: We don't fill in the entire width of the projection because the accounts adapter
|
|
||||||
* only looks at a few of the columns anyway.
|
|
||||||
*/
|
|
||||||
private void populateLowerCursor() {
|
|
||||||
MatrixCursor childCursor = (MatrixCursor) mLowerCursor;
|
|
||||||
|
|
||||||
RowBuilder row;
|
|
||||||
// Account #1
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(1)); // CONTENT_ID_COLUMN = 0;
|
|
||||||
row.add("Account 1"); // CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
||||||
row.add("account1@android.com"); // CONTENT_EMAIL_ADDRESS_COLUMN = 2;
|
|
||||||
// Account #2
|
|
||||||
row = childCursor.newRow();
|
|
||||||
row.add(Long.valueOf(2)); // CONTENT_ID_COLUMN = 0;
|
|
||||||
row.add("Account 2"); // CONTENT_DISPLAY_NAME_COLUMN = 1;
|
|
||||||
row.add("account2@android.com"); // CONTENT_EMAIL_ADDRESS_COLUMN = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test: General handling of separator
|
|
||||||
*/
|
|
||||||
public void testSeparator() {
|
|
||||||
// Test with fully populated upper and lower sections
|
|
||||||
setupUpperCursor();
|
|
||||||
populateUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
populateLowerCursor();
|
|
||||||
AccountsAdapter adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor,
|
|
||||||
getContext(), -1, null);
|
|
||||||
checkAdapter("fully populated", adapter, mUpperCursor, mLowerCursor);
|
|
||||||
|
|
||||||
// Test with empty upper and populated lower
|
|
||||||
setupUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
populateLowerCursor();
|
|
||||||
adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor, getContext(), -1, null);
|
|
||||||
checkAdapter("lower populated", adapter, mUpperCursor, mLowerCursor);
|
|
||||||
|
|
||||||
// Test with both empty
|
|
||||||
setupUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor, getContext(), -1, null);
|
|
||||||
checkAdapter("both empty", adapter, mUpperCursor, mLowerCursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to check the various APIs related to the upper/lower separator
|
|
||||||
*/
|
|
||||||
private void checkAdapter(String tag, AccountsAdapter adapter, Cursor upper, Cursor lower) {
|
|
||||||
// Check total count
|
|
||||||
int expectedCount = 0;
|
|
||||||
if (upper != null) expectedCount += upper.getCount();
|
|
||||||
if (lower != null) expectedCount += lower.getCount();
|
|
||||||
// If one or more items are shown, the adapter inserts the separator as well
|
|
||||||
if (expectedCount > 0) expectedCount++;
|
|
||||||
assertEquals(tag, expectedCount, adapter.getCount());
|
|
||||||
|
|
||||||
// Check separator-related APIs
|
|
||||||
int separatorIndex = -1;
|
|
||||||
if (upper != null) {
|
|
||||||
separatorIndex = upper.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the MergeCursor that the adapter created
|
|
||||||
MergeCursor mc = (MergeCursor) adapter.getCursor();
|
|
||||||
|
|
||||||
// Check APIs for the position above the separator index
|
|
||||||
// This will be the last entry in the "upper" cursor
|
|
||||||
if (separatorIndex > 0) {
|
|
||||||
int checkIndex = separatorIndex - 1;
|
|
||||||
assertTrue(tag, adapter.isMailbox(checkIndex));
|
|
||||||
assertFalse(tag, adapter.isAccount(checkIndex));
|
|
||||||
assertTrue(tag, adapter.isEnabled(checkIndex));
|
|
||||||
Cursor c = (Cursor) adapter.getItem(checkIndex);
|
|
||||||
assertEquals(tag, mc, c);
|
|
||||||
assertEquals(tag, checkIndex, c.getPosition());
|
|
||||||
upper.moveToLast();
|
|
||||||
long id = upper.getLong(0);
|
|
||||||
assertEquals(tag, id, adapter.getItemId(checkIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check APIs for position at the separator index
|
|
||||||
if (separatorIndex >= 0) {
|
|
||||||
int checkIndex = separatorIndex;
|
|
||||||
assertFalse(tag, adapter.isMailbox(checkIndex));
|
|
||||||
assertFalse(tag, adapter.isAccount(checkIndex));
|
|
||||||
assertFalse(tag, adapter.isEnabled(checkIndex));
|
|
||||||
// getItem and getItemId should never be called because it should not be enabled
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check APIs for the position below the separator index
|
|
||||||
// This will be the first entry in the "lower" cursor
|
|
||||||
if (lower != null && lower.getCount() > 0) {
|
|
||||||
int checkIndex = separatorIndex + 1;
|
|
||||||
assertFalse(tag, adapter.isMailbox(checkIndex));
|
|
||||||
assertTrue(tag, adapter.isAccount(checkIndex));
|
|
||||||
assertTrue(tag, adapter.isEnabled(checkIndex));
|
|
||||||
Cursor c = (Cursor) adapter.getItem(checkIndex);
|
|
||||||
assertEquals(tag, mc, c);
|
|
||||||
assertEquals(tag, separatorIndex, c.getPosition());
|
|
||||||
lower.moveToFirst();
|
|
||||||
long id = lower.getLong(0);
|
|
||||||
assertEquals(tag, id, adapter.getItemId(checkIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test: isOnDeletingAccountView
|
|
||||||
*/
|
|
||||||
public void testDeletingAccount() {
|
|
||||||
// Test with fully populated upper and lower sections
|
|
||||||
setupUpperCursor();
|
|
||||||
populateUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
populateLowerCursor();
|
|
||||||
AccountsAdapter adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor,
|
|
||||||
getContext(), -1, null);
|
|
||||||
|
|
||||||
// Check enabled state - all should be enabled except for separator
|
|
||||||
for (int i = 0; i < adapter.getCount(); i++) {
|
|
||||||
boolean expectEnabled = adapter.isMailbox(i) || adapter.isAccount(i);
|
|
||||||
assertEquals(expectEnabled, adapter.isEnabled(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Delete" the first account
|
|
||||||
adapter.addOnDeletingAccount(1); // account Id of 1st account
|
|
||||||
int account1Position = mUpperCursor.getCount() + 1; // first entry after separator
|
|
||||||
for (int i = 0; i < adapter.getCount(); i++) {
|
|
||||||
boolean isNotSeparator = adapter.isMailbox(i) || adapter.isAccount(i);
|
|
||||||
boolean expectEnabled = isNotSeparator && (i != account1Position);
|
|
||||||
assertEquals(expectEnabled, adapter.isEnabled(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test: callback(s)
|
|
||||||
*/
|
|
||||||
public void testCallbacks() {
|
|
||||||
// Test with fully populated upper and lower sections
|
|
||||||
setupUpperCursor();
|
|
||||||
populateUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
populateLowerCursor();
|
|
||||||
Callback cb = new Callback();
|
|
||||||
AccountsAdapter adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor,
|
|
||||||
getContext(), -1, cb);
|
|
||||||
|
|
||||||
AccountFolderListItem itemView = new AccountFolderListItem(mContext);
|
|
||||||
itemView.mAccountId = 1;
|
|
||||||
adapter.onClickFolder(itemView);
|
|
||||||
assertTrue(cb.called);
|
|
||||||
assertEquals(1, cb.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Callback implements AccountsAdapter.Callback {
|
|
||||||
public boolean called = false;
|
|
||||||
public long id = -1;
|
|
||||||
|
|
||||||
public void onClickAccountFolders(long accountId) {
|
|
||||||
called = true;
|
|
||||||
id = accountId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for cursor management. Make sure that the underlying cursor is closed properly
|
|
||||||
* when we set the cursor to null.
|
|
||||||
*/
|
|
||||||
public void testCursorManagement() {
|
|
||||||
setupUpperCursor();
|
|
||||||
setupLowerCursor();
|
|
||||||
AccountsAdapter adapter = AccountsAdapter.getInstance(mUpperCursor, mLowerCursor,
|
|
||||||
getContext(), -1, null);
|
|
||||||
|
|
||||||
Cursor c = adapter.getCursor();
|
|
||||||
assertFalse(c.isClosed());
|
|
||||||
adapter.changeCursor(null);
|
|
||||||
assertTrue(c.isClosed());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,7 +27,7 @@ import android.net.Uri;
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
import android.test.ActivityInstrumentationTestCase2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test case for {@link MessageTestView}.
|
* Test case for {@link MessageFileView}.
|
||||||
*
|
*
|
||||||
* TODO Add more tests. Any good way to test fragment??
|
* TODO Add more tests. Any good way to test fragment??
|
||||||
*/
|
*/
|
||||||
|
@ -49,7 +49,7 @@ public class MessageFileViewTest extends ActivityInstrumentationTestCase2<Messag
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpIntent(Uri uri) {
|
private void setUpIntent(Uri uri) {
|
||||||
final Intent i = new Intent(getInstrumentation().getTargetContext(), MessageView.class);
|
final Intent i = new Intent(getInstrumentation().getTargetContext(), MessageFileView.class);
|
||||||
i.setData(uri);
|
i.setData(uri);
|
||||||
setActivityIntent(i);
|
setActivityIntent(i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 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.email.activity;
|
|
||||||
|
|
||||||
import com.android.email.DBTestHelper;
|
|
||||||
import com.android.email.TestUtils;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.test.ActivityInstrumentationTestCase2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test case for {@link MessageView}.
|
|
||||||
*
|
|
||||||
* TODO Add more tests. Any good way to test fragment??
|
|
||||||
*/
|
|
||||||
public class MessageViewTest extends ActivityInstrumentationTestCase2<MessageView> {
|
|
||||||
private static final String EXTRA_MESSAGE_ID = "com.android.email.MessageView_message_id";
|
|
||||||
private static final String EXTRA_DISABLE_REPLY =
|
|
||||||
"com.android.email.MessageView_disable_reply";
|
|
||||||
private static final String EXTRA_MAILBOX_ID = "com.android.email.MessageView_mailbox_id";
|
|
||||||
|
|
||||||
private static int TIMEOUT = 10; // in seconds
|
|
||||||
|
|
||||||
private Context mProviderContext;
|
|
||||||
|
|
||||||
public MessageViewTest() {
|
|
||||||
super(MessageView.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
mProviderContext = DBTestHelper.ProviderContextSetupHelper.getProviderContext(
|
|
||||||
getInstrumentation().getTargetContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setUpIntent(long messageId, long mailboxId, boolean disableReply) {
|
|
||||||
final Intent i = new Intent(getInstrumentation().getTargetContext(), MessageView.class);
|
|
||||||
i.putExtra(EXTRA_MESSAGE_ID, messageId);
|
|
||||||
i.putExtra(EXTRA_MAILBOX_ID, mailboxId);
|
|
||||||
if (disableReply) {
|
|
||||||
i.putExtra(EXTRA_DISABLE_REPLY, true);
|
|
||||||
}
|
|
||||||
setActivityIntent(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the activity without setting an Intent.
|
|
||||||
*
|
|
||||||
* Expected: Activity will close itself.
|
|
||||||
*/
|
|
||||||
public void testCreateWithoutParamter() throws Throwable {
|
|
||||||
// No intent parameters specified. The activity will close itself.
|
|
||||||
final MessageView activity = getActivity();
|
|
||||||
|
|
||||||
TestUtils.waitUntil("", new TestUtils.Condition() {
|
|
||||||
@Override
|
|
||||||
public boolean isMet() {
|
|
||||||
return activity.isFinishing();
|
|
||||||
}
|
|
||||||
}, TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This test doesn't work, because it sets up messages in an separated context, but
|
|
||||||
// the main activity looks at the actual context and fails to find the message.
|
|
||||||
// /**
|
|
||||||
// * Set up account/mailbox/message, and open the activity.
|
|
||||||
// *
|
|
||||||
// * Expected: Message opens.
|
|
||||||
// */
|
|
||||||
// public void testOpenMessage() throws Exception {
|
|
||||||
// final Context c = mProviderContext;
|
|
||||||
// final Account acct1 = ProviderTestUtils.setupAccount("test1", true, c);
|
|
||||||
// final Account acct2 = ProviderTestUtils.setupAccount("test2", true, c);
|
|
||||||
// final Mailbox acct2inbox = ProviderTestUtils.setupMailbox("inbox", acct2.mId, true, c);
|
|
||||||
// final Message msg1 = ProviderTestUtils.setupMessage("message1", acct2.mId, acct2inbox.mId,
|
|
||||||
// true, true, c);
|
|
||||||
// final Message msg2 = ProviderTestUtils.setupMessage("message2", acct2.mId, acct2inbox.mId,
|
|
||||||
// true, true, c);
|
|
||||||
//
|
|
||||||
// setUpIntent(msg2.mId, msg2.mMailboxKey, false);
|
|
||||||
//
|
|
||||||
// final MessageView activity = getActivity();
|
|
||||||
//
|
|
||||||
// TestUtils.waitUntil(new TestUtils.Condition() {
|
|
||||||
// @Override
|
|
||||||
// public boolean isMet() {
|
|
||||||
// MessageViewFragment f = activity.getFragment();
|
|
||||||
// return f != null && f.isMessageLoadedForTest();
|
|
||||||
// }
|
|
||||||
// }, TIMEOUT);
|
|
||||||
//
|
|
||||||
// // TODO Check UI elements, once our UI is settled.
|
|
||||||
// }
|
|
||||||
}
|
|