summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Soulos <psoulos@google.com>2014-07-24 14:08:11 -0700
committerPaul Soulos <psoulos@google.com>2014-07-24 14:29:25 -0700
commit5d22c41a997c88cf6e44b53a4a76617944f16e53 (patch)
tree0b1175ad6ca8d05a0aad5a9f914fa74b7e5befb9
parent2e07da704662e9926ba83714188d156cc8b6511e (diff)
downloadpackages_apps_Contacts-5d22c41a997c88cf6e44b53a4a76617944f16e53.tar.gz
packages_apps_Contacts-5d22c41a997c88cf6e44b53a4a76617944f16e53.tar.bz2
packages_apps_Contacts-5d22c41a997c88cf6e44b53a4a76617944f16e53.zip
Remove ContactDetail code.
Bug: 16457366 Change-Id: I79367304bb7a0dfdc2b420580f8d8207ef602856
-rw-r--r--res/drawable-hdpi/ic_list_default_mime_holo_dark.pngbin487 -> 0 bytes
-rw-r--r--res/drawable-mdpi/ic_list_default_mime_holo_dark.pngbin414 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/ic_list_default_mime_holo_dark.pngbin598 -> 0 bytes
-rw-r--r--res/drawable-xxhdpi/ic_list_default_mime_holo_dark.pngbin1464 -> 0 bytes
-rw-r--r--res/layout-land/contact_detail_fragment.xml81
-rw-r--r--res/layout-land/detail_header_contact_with_updates.xml24
-rw-r--r--res/layout-land/detail_header_contact_without_updates.xml24
-rw-r--r--res/layout-sw600dp-land/contact_detail_fragment.xml69
-rw-r--r--res/layout-sw600dp-land/detail_header_contact_without_updates.xml59
-rw-r--r--res/layout-sw600dp/contact_detail_fragment.xml51
-rw-r--r--res/layout-sw600dp/detail_header_contact_without_updates.xml89
-rw-r--r--res/layout-sw720dp-land/contact_detail_empty.xml36
-rw-r--r--res/layout-sw720dp-land/contact_detail_fragment.xml71
-rw-r--r--res/layout-sw720dp-land/contact_detail_list_item.xml124
-rw-r--r--res/layout-sw720dp-land/detail_header_contact_without_updates.xml56
-rw-r--r--res/layout/contact_detail_activity.xml37
-rw-r--r--res/layout/contact_detail_container.xml25
-rw-r--r--res/layout/contact_detail_empty.xml29
-rw-r--r--res/layout/contact_detail_fragment.xml62
-rw-r--r--res/layout/contact_detail_list_item.xml112
-rw-r--r--res/layout/contact_detail_loader_fragment.xml26
-rw-r--r--res/layout/detail_header_contact_without_updates.xml46
-rw-r--r--res/layout/photo_selector_view.xml39
-rw-r--r--res/values/dimens.xml19
-rw-r--r--res/values/strings.xml6
-rw-r--r--res/values/styles.xml8
-rw-r--r--src/com/android/contacts/activities/ContactDetailActivity.java279
-rw-r--r--src/com/android/contacts/activities/PeopleActivity.java2
-rw-r--r--src/com/android/contacts/detail/ContactDetailFragment.java2250
-rw-r--r--src/com/android/contacts/detail/ContactDetailLayoutController.java138
-rw-r--r--src/com/android/contacts/detail/ContactLoaderFragment.java474
-rw-r--r--tests/src/com/android/contacts/ContactDetailTest.java59
-rw-r--r--tests/src/com/android/contacts/activities/PeopleActivityTest.java1
33 files changed, 1 insertions, 4295 deletions
diff --git a/res/drawable-hdpi/ic_list_default_mime_holo_dark.png b/res/drawable-hdpi/ic_list_default_mime_holo_dark.png
deleted file mode 100644
index 4dc1c3934..000000000
--- a/res/drawable-hdpi/ic_list_default_mime_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_list_default_mime_holo_dark.png b/res/drawable-mdpi/ic_list_default_mime_holo_dark.png
deleted file mode 100644
index d950b316c..000000000
--- a/res/drawable-mdpi/ic_list_default_mime_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_list_default_mime_holo_dark.png b/res/drawable-xhdpi/ic_list_default_mime_holo_dark.png
deleted file mode 100644
index 73cddd16b..000000000
--- a/res/drawable-xhdpi/ic_list_default_mime_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_list_default_mime_holo_dark.png b/res/drawable-xxhdpi/ic_list_default_mime_holo_dark.png
deleted file mode 100644
index 4f12d9516..000000000
--- a/res/drawable-xxhdpi/ic_list_default_mime_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/layout-land/contact_detail_fragment.xml b/res/layout-land/contact_detail_fragment.xml
deleted file mode 100644
index 2d788df53..000000000
--- a/res/layout-land/contact_detail_fragment.xml
+++ /dev/null
@@ -1,81 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/contact_detail"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- "QuickFix"- button (Copy to local contact, add to group) -->
- <Button
- android:id="@+id/contact_quick_fix"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentBottom="true"
- android:layout_marginRight="40dip"
- android:layout_marginEnd="40dip"
- android:layout_marginTop="20dip"
- android:layout_marginBottom="20dip" />
-
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_above="@id/contact_quick_fix"
- android:layout_height="match_parent"
- android:baselineAligned="false"
- android:background="@android:color/white">
-
- <include android:id="@+id/static_photo_container"
- layout="@layout/photo_selector_view"
- android:layout_width="@dimen/detail_contact_photo_size"
- android:layout_height="@dimen/detail_contact_photo_size"
- android:layout_marginLeft="@dimen/detail_contact_photo_margin"
- android:layout_marginStart="@dimen/detail_contact_photo_margin"
- android:layout_marginTop="@dimen/detail_contact_photo_margin" />
-
- <ListView android:id="@android:id/list"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:fadingEdge="none"
- android:layout_weight="1"
- android:divider="@null"/>
-
- </LinearLayout>
-
- <ScrollView android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="0px"
- android:fadingEdge="none"
- android:visibility="gone">
- <TextView android:id="@+id/emptyText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- android:paddingStart="10dip"
- android:paddingEnd="10dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"/>
- </ScrollView>
-
-</RelativeLayout>
-
diff --git a/res/layout-land/detail_header_contact_with_updates.xml b/res/layout-land/detail_header_contact_with_updates.xml
deleted file mode 100644
index 588957e94..000000000
--- a/res/layout-land/detail_header_contact_with_updates.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact has social updates.
- This is empty because all the information will be displayed elsewhere.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dip"/> \ No newline at end of file
diff --git a/res/layout-land/detail_header_contact_without_updates.xml b/res/layout-land/detail_header_contact_without_updates.xml
deleted file mode 100644
index 44ea04cca..000000000
--- a/res/layout-land/detail_header_contact_without_updates.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact does not have social
- updates. This is empty because all the information will be displayed elsewhere.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="0dip"/> \ No newline at end of file
diff --git a/res/layout-sw600dp-land/contact_detail_fragment.xml b/res/layout-sw600dp-land/contact_detail_fragment.xml
deleted file mode 100644
index a48a5b50a..000000000
--- a/res/layout-sw600dp-land/contact_detail_fragment.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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:id="@+id/contact_detail"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- Placeholder for empty list -->
- <include
- android:id="@android:id/empty"
- layout="@layout/contact_detail_empty"
- android:visibility="gone" />
-
- <!-- Real list -->
- <LinearLayout
- android:orientation="horizontal"
- android:layout_weight="1"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:baselineAligned="false">
-
- <include android:id="@+id/static_photo_container"
- layout="@layout/photo_selector_view"
- android:layout_width="@dimen/detail_contact_photo_size"
- android:layout_height="@dimen/detail_contact_photo_size"
- android:layout_marginTop="@dimen/detail_contact_photo_margin"
- android:layout_marginRight="@dimen/detail_contact_photo_margin"
- android:layout_marginEnd="@dimen/detail_contact_photo_margin" />
-
- <ListView android:id="@android:id/list"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:paddingTop="16dip"
- android:clipToPadding="false"
- android:fadingEdge="none"
- android:layout_weight="1"
- android:divider="@null"
- android:scrollbarStyle="outsideOverlay"
- android:paddingRight="16dip"
- android:paddingEnd="16dip"/>
-
- </LinearLayout>
-
- <!-- "QuickFix"- button (Copy to local contact, add to group) -->
- <Button
- android:id="@+id/contact_quick_fix"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_gravity="center"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip" />
-</LinearLayout>
diff --git a/res/layout-sw600dp-land/detail_header_contact_without_updates.xml b/res/layout-sw600dp-land/detail_header_contact_without_updates.xml
deleted file mode 100644
index 085b972f0..000000000
--- a/res/layout-sw600dp-land/detail_header_contact_without_updates.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact does not have social
- updates, which means that the contact's basic info will scroll with the list of details. The
- photo is not included because it will be displayed in a static place elsewhere.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="8dip"
- android:paddingStart="8dip"
- android:paddingBottom="16dip"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="16dip"
- android:paddingEnd="16dip">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size"
- android:paddingRight="16dip"
- android:paddingEnd="16dip" />
-
- <include
- layout="@layout/favorites_star" />
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
-</LinearLayout>
diff --git a/res/layout-sw600dp/contact_detail_fragment.xml b/res/layout-sw600dp/contact_detail_fragment.xml
deleted file mode 100644
index 1e0f7e6b5..000000000
--- a/res/layout-sw600dp/contact_detail_fragment.xml
+++ /dev/null
@@ -1,51 +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:id="@+id/contact_detail"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- Placeholder for empty list -->
- <include
- android:id="@android:id/empty"
- layout="@layout/contact_detail_empty"
- android:visibility="gone" />
-
- <!-- Real list -->
- <ListView android:id="@android:id/list"
- android:layout_weight="1"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:fadingEdge="none"
- android:cacheColorHint="#00000000"
- android:divider="@null"
- android:scrollbarStyle="outsideOverlay"
- android:paddingRight="12dip"
- android:paddingEnd="12dip" />
-
- <!-- "QuickFix"- button (Copy to local contact, add to group) -->
- <Button
- android:id="@+id/contact_quick_fix"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_gravity="center"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip" />
-</LinearLayout>
diff --git a/res/layout-sw600dp/detail_header_contact_without_updates.xml b/res/layout-sw600dp/detail_header_contact_without_updates.xml
deleted file mode 100644
index 069e0dee4..000000000
--- a/res/layout-sw600dp/detail_header_contact_without_updates.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact does not have social
- updates, which means that the contact's photo and basic info will scroll with the list of details.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingBottom="16dip">
-
- <!-- Ensure that the contact photo for a contact WITHOUT social updates is the same width and
- height as a contact WITH social updates (where the photo is 2/3 of the screen width). -->
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- ex:ratio="0.6667"
- ex:direction="widthToHeight">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal">
-
- <include layout="@layout/photo_selector_view"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="2" />
-
- <!-- Empty view to fill the rest of the LinearLayout, so that a weight on its sibling
- ImageView will work.-->
- <View
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="match_parent" />
-
- </LinearLayout>
-
- </view>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="8dip"
- android:paddingEnd="8dip" >
-
- <TextView
- android:id="@+id/name"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingStart="8dip"
- android:paddingEnd="24dip"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size" />
-
- <include
- layout="@layout/favorites_star" />
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
-</LinearLayout>
diff --git a/res/layout-sw720dp-land/contact_detail_empty.xml b/res/layout-sw720dp-land/contact_detail_empty.xml
deleted file mode 100644
index 0ff996092..000000000
--- a/res/layout-sw720dp-land/contact_detail_empty.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<!-- Placeholder for empty details for a contact -->
-
-<com.android.contacts.widget.InterpolatingLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/emptyText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- ex:layout_wideParentWidth="800dip"
- ex:layout_wideMarginLeft="80dip"
- ex:layout_narrowParentWidth="500dip"
- ex:layout_narrowMarginLeft="44dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"/>
-</com.android.contacts.widget.InterpolatingLayout>
diff --git a/res/layout-sw720dp-land/contact_detail_fragment.xml b/res/layout-sw720dp-land/contact_detail_fragment.xml
deleted file mode 100644
index 4eee458ff..000000000
--- a/res/layout-sw720dp-land/contact_detail_fragment.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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:id="@+id/contact_detail"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="16dip"
- android:paddingStart="16dip">
-
- <!-- Placeholder for empty list -->
- <include
- android:id="@android:id/empty"
- layout="@layout/contact_detail_empty"
- android:visibility="gone" />
-
- <!-- Real list -->
- <LinearLayout
- android:orientation="horizontal"
- android:layout_weight="1"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:baselineAligned="false">
-
- <include android:id="@+id/static_photo_container"
- layout="@layout/photo_selector_view"
- android:layout_width="@dimen/detail_contact_photo_size"
- android:layout_height="@dimen/detail_contact_photo_size"
- android:layout_marginTop="@dimen/detail_contact_photo_margin"
- android:layout_marginRight="@dimen/detail_contact_photo_margin"
- android:layout_marginEnd="@dimen/detail_contact_photo_margin" />
-
- <ListView android:id="@android:id/list"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:paddingTop="16dip"
- android:clipToPadding="false"
- android:fadingEdge="none"
- android:layout_weight="1"
- android:divider="@null"
- android:paddingRight="16dip"
- android:paddingEnd="16dip"
- android:scrollbarStyle="outsideOverlay"/>
-
- </LinearLayout>
-
- <!-- "QuickFix"- button (Copy to local contact, add to group) -->
- <Button
- android:id="@+id/contact_quick_fix"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_gravity="center"
- android:layout_marginTop="10dip"
- android:layout_marginBottom="10dip" />
-</LinearLayout>
diff --git a/res/layout-sw720dp-land/contact_detail_list_item.xml b/res/layout-sw720dp-land/contact_detail_list_item.xml
deleted file mode 100644
index a5af1ddae..000000000
--- a/res/layout-sw720dp-land/contact_detail_list_item.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 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.
- */
--->
-
-<!-- Note: padding might be controlled programatically -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="16dip"
- android:paddingStart="16dip">
-
- <com.android.contacts.detail.ActionsViewContainer
- android:id="@+id/actions_view_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="@dimen/detail_min_line_item_height"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackground"
- android:nextFocusRight="@+id/secondary_action_view_container">
-
- <!-- Note: padding might be controlled programatically -->
- <LinearLayout
- android:id="@+id/primary_action_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:paddingLeft="8dip"
- android:paddingStart="8dip"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- </LinearLayout>
-
- <ImageView
- android:id="@+id/presence_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="1dip"
- android:layout_marginRight="4dip"
- android:layout_marginEnd="4dip"
- android:layout_gravity="center_vertical"
- android:scaleType="centerInside" />
-
- <TextView
- android:id="@+id/kind"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:visibility="gone" />
-
- <View
- android:id="@+id/primary_indicator"
- android:layout_width="16dip"
- android:layout_height="16dip"
- android:visibility="gone"
- android:layout_gravity="center_vertical"
- android:background="@drawable/ic_list_default_mime_holo_dark"
- android:layout_marginRight="8dip"
- android:layout_marginEnd="8dip" />
-
- <TextView
- android:id="@+id/type"
- style="@style/ContactDetailItemType"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="16dip"
- android:paddingEnd="16dip" />
-
- <View
- android:id="@+id/vertical_divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="@dimen/detail_vertical_divider_vertical_margin"
- android:layout_marginBottom="@dimen/detail_vertical_divider_vertical_margin"
- android:background="?android:attr/dividerVertical" />
-
- <!-- Note: padding might be controlled programatically -->
- <FrameLayout
- android:id="@+id/secondary_action_view_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="@dimen/detail_item_icon_margin"
- android:paddingRight="@dimen/detail_item_icon_margin"
- android:paddingStart="@dimen/detail_item_icon_margin"
- android:paddingEnd="@dimen/detail_item_icon_margin"
- android:duplicateParentState="false"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackground"
- android:nextFocusLeft="@id/actions_view_container">
- <ImageView
- android:id="@+id/secondary_action_button"
- android:layout_width="32dip"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:gravity="center"
- android:scaleType="center"
- android:duplicateParentState="false" />
- </FrameLayout>
- </com.android.contacts.detail.ActionsViewContainer>
-</FrameLayout>
diff --git a/res/layout-sw720dp-land/detail_header_contact_without_updates.xml b/res/layout-sw720dp-land/detail_header_contact_without_updates.xml
deleted file mode 100644
index bc3f16ca0..000000000
--- a/res/layout-sw720dp-land/detail_header_contact_without_updates.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact does not have social
- updates, which means that the contact's basic info will scroll with the list of details. The
- photo is not included because it will be displayed in a static place elsewhere.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:paddingBottom="16dip"
- android:orientation="vertical">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingEnd="16dip">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="0dip"
- android:layout_weight="1"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size"
- android:paddingStart="16dip" />
-
- <include
- layout="@layout/favorites_star" />
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/res/layout/contact_detail_activity.xml b/res/layout/contact_detail_activity.xml
deleted file mode 100644
index 9765a7187..000000000
--- a/res/layout/contact_detail_activity.xml
+++ /dev/null
@@ -1,37 +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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/contact_detail_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <!-- This fragment is an invisible worker fragment that loads the contact details. -->
- <fragment
- android:id="@+id/loader_fragment"
- class="com.android.contacts.detail.ContactLoaderFragment"
- android:layout_height="0dip"
- android:layout_width="0dip"
- android:visibility="gone"/>
-
- <!-- This layout includes all possible views needed for a contact detail page -->
- <include
- android:id="@+id/contact_detail_container"
- layout="@layout/contact_detail_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
-</FrameLayout>
diff --git a/res/layout/contact_detail_container.xml b/res/layout/contact_detail_container.xml
deleted file mode 100644
index 910d68450..000000000
--- a/res/layout/contact_detail_container.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<!-- Layout for the contact card page. -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <fragment android:name="com.android.contacts.detail.ContactDetailFragment"
- android:id="@+id/contact_detail_about_fragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-</FrameLayout> \ No newline at end of file
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/contact_detail_empty.xml
deleted file mode 100644
index cdb8feb9b..000000000
--- a/res/layout/contact_detail_empty.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<!-- Placeholder for empty details for a contact -->
-
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:layout_marginStart="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"/> \ No newline at end of file
diff --git a/res/layout/contact_detail_fragment.xml b/res/layout/contact_detail_fragment.xml
deleted file mode 100644
index 4d53310fe..000000000
--- a/res/layout/contact_detail_fragment.xml
+++ /dev/null
@@ -1,62 +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:id="@+id/contact_detail_about_fragment"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ListView android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="0px"
- android:layout_weight="1"
- android:fadingEdge="none"
- android:divider="@null"/>
-
- <ScrollView android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="0px"
- android:layout_weight="1"
- android:fadingEdge="none"
- android:visibility="gone">
-
- <TextView android:id="@+id/emptyText"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:paddingLeft="10dip"
- android:paddingRight="10dip"
- android:paddingStart="10dip"
- android:paddingEnd="10dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"/>
-
- </ScrollView>
-
- <!-- "QuickFix"- button (Copy to local contact, add to group) -->
- <Button
- android:id="@+id/contact_quick_fix"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layout_gravity="center"
- android:layout_marginTop="20dip"
- android:layout_marginBottom="20dip" />
-</LinearLayout>
-
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
deleted file mode 100644
index fb24caae4..000000000
--- a/res/layout/contact_detail_list_item.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 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.
- */
--->
-
-<!-- Note: padding might be controlled programatically -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="16dip">
-
- <com.android.contacts.detail.ActionsViewContainer
- android:id="@+id/actions_view_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackground"
- android:nextFocusRight="@+id/secondary_action_view_container"
- android:minHeight="@dimen/detail_min_line_item_height">
-
- <!-- Note: padding might be controlled programatically -->
- <LinearLayout
- android:id="@+id/primary_action_view"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingStart="8dip" >
-
- <TextView
- android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/presence_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="1dip"
- android:layout_marginRight="4dip"
- android:layout_marginEnd="4dip"
- android:layout_gravity="center_vertical"
- android:gravity="center"
- android:scaleType="centerInside" />
-
- <TextView
- android:id="@+id/type"
- style="@style/ContactDetailItemType"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <View
- android:id="@+id/primary_indicator"
- android:layout_width="16dip"
- android:layout_height="16dip"
- android:visibility="gone"
- android:layout_gravity="center_vertical"
- android:background="@drawable/ic_list_default_mime_holo_dark" />
-
- </LinearLayout>
-
- </LinearLayout>
-
- <View
- android:id="@+id/vertical_divider"
- android:layout_width="1dip"
- android:layout_height="match_parent"
- android:layout_marginTop="@dimen/detail_vertical_divider_vertical_margin"
- android:layout_marginBottom="@dimen/detail_vertical_divider_vertical_margin"
- android:background="?android:attr/dividerVertical" />
-
- <!-- Note: padding might be controlled programatically -->
- <FrameLayout
- android:id="@+id/secondary_action_view_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingStart="@dimen/detail_item_icon_margin"
- android:paddingEnd="@dimen/detail_item_icon_margin"
- android:focusable="true"
- android:background="?android:attr/selectableItemBackground"
- android:nextFocusLeft="@id/actions_view_container">
- <ImageView
- android:id="@+id/secondary_action_button"
- android:layout_width="32dip"
- android:layout_height="32dip"
- android:layout_gravity="center_vertical"
- android:duplicateParentState="false" />
- </FrameLayout>
- </com.android.contacts.detail.ActionsViewContainer>
-</FrameLayout>
diff --git a/res/layout/contact_detail_loader_fragment.xml b/res/layout/contact_detail_loader_fragment.xml
deleted file mode 100644
index 62edb3d41..000000000
--- a/res/layout/contact_detail_loader_fragment.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<!--
- Invisible view.
- Note we show/hide the fragment at runtime with FragmentTransaction.show()/hide() in order to
- change the visibility of the options menu. This means the visibility of the view will be
- changed at runtime, so we use width/height to make it invisible, rather than using
- visibility.
--->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="0dip"
- android:layout_height="0dip"/> \ No newline at end of file
diff --git a/res/layout/detail_header_contact_without_updates.xml b/res/layout/detail_header_contact_without_updates.xml
deleted file mode 100644
index 27f6288aa..000000000
--- a/res/layout/detail_header_contact_without_updates.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact does not have social
- updates, which means that the contact's photo will scroll with the list of details.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <!-- Contact photo -->
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- ex:ratio="0.5"
- ex:direction="widthToHeight">
-
- <include layout="@layout/photo_selector_view" />
-
- </view>
-
- <!-- Shadow -->
- <View
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_contact_photo_shadow_height"
- android:background="?android:attr/windowContentOverlay"/>
-
-</LinearLayout>
diff --git a/res/layout/photo_selector_view.xml b/res/layout/photo_selector_view.xml
deleted file mode 100644
index 1a21c3019..000000000
--- a/res/layout/photo_selector_view.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- View for displaying photos that show a photo selector when clicked.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ImageView
- android:id="@+id/photo"
- android:scaleType="centerCrop"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <View
- android:id="@+id/photo_touch_intercept_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground"
- android:visibility="gone"
- android:contentDescription="@string/contact_detail_picture_description"/>
-
-</FrameLayout>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7c6b6350b..f0376f6b6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -53,15 +53,6 @@
<!-- Left padding of the label in the add field button for the contact editor -->
<dimen name="editor_add_field_label_left_padding">16dip</dimen>
- <!-- Height of the shadow asset under the photo on the contact detail page -->
- <dimen name="detail_contact_photo_shadow_height">10dip</dimen>
-
- <!-- Margin around the contact's photo on the contact card -->
- <dimen name="detail_contact_photo_margin">8dip</dimen>
-
- <!-- Width and height of the contact photo on the contact detail page -->
- <dimen name="detail_contact_photo_size">128dip</dimen>
-
<!-- Width and height of the expanded contact photo on the contact detail page -->
<dimen name="detail_contact_photo_expanded_size">400dip</dimen>
@@ -72,22 +63,12 @@
<!-- Minimum width for the photo action popup options -->
<dimen name="photo_action_popup_min_width">300dip</dimen>
- <!-- Left and right padding for a contact detail item -->
- <dimen name="detail_item_icon_margin">8dip</dimen>
-
<!-- Top and bottom padding for a contact detail item -->
<dimen name="detail_item_vertical_margin">8dip</dimen>
<!-- Minimum height of a row in the contact detail -->
<dimen name="detail_min_line_item_height">48dip</dimen>
- <!-- Font size for the display name in header of the contact detail page -->
- <dimen name="detail_header_name_text_size">36sp</dimen>
-
- <!-- Vertical margin for vertical dividers existing between primary data
- (phone number, email, etc.) and a secondary action button -->
- <dimen name="detail_vertical_divider_vertical_margin">16dip</dimen>
-
<!-- Font size used for the contact name in the widget -->
<dimen name="widget_text_size_name">14sp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9583fcb6f..4d07bc7f1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -372,9 +372,6 @@
<!-- Text used to explain that a contact cannot be edited from the People application since the data is read only [CHAR LIMIT=40] -->
<string name="contact_read_only">Not editable from this app.</string>
- <!-- Text describing that a contact has no information available other than name and photo. [CHAR LIMIT=60] -->
- <string name="no_contact_details">No additional information for this contact.</string>
-
<!-- Text used to explain that a group cannot be edited since the data is read only [CHAR LIMIT=40] -->
<string name="group_read_only">Not editable on this device.</string>
@@ -646,9 +643,6 @@
<!-- Menu item shown only when the special debug mode is enabled, which is used to send all contacts database files via email. [CHAR LIMI=NONE] -->
<string name="menu_export_database">Export database files</string>
- <!-- Description when picture in the contact detail view is selected. [CHAR LIMIT=NONE] -->
- <string name="contact_detail_picture_description">Picture. Select to change</string>
-
<!-- Content description for the button that adds a new contact
[CHAR LIMIT=NONE] -->
<string name="action_menu_add_new_contact_button">add new contact</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index af3c031f2..815b5b0a9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -202,14 +202,6 @@
<item name="android:layout_width">match_parent</item>
</style>
- <style name="ContactDetailItemType">
- <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
- <item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:singleLine">true</item>
- <item name="android:ellipsize">marquee</item>
- <item name="android:layout_gravity">center_vertical</item>
- </style>
-
<style name="ConfirmAddDetailViewStyle">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
deleted file mode 100644
index 849923d89..000000000
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ /dev/null
@@ -1,279 +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.contacts.activities;
-
-import android.app.ActionBar;
-import android.app.Fragment;
-import android.content.ActivityNotFoundException;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.MenuItem.OnMenuItemClickListener;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.Toast;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.R;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.detail.ContactDetailFragment;
-import com.android.contacts.detail.ContactDetailLayoutController;
-import com.android.contacts.detail.ContactDisplayUtils;
-import com.android.contacts.detail.ContactLoaderFragment;
-import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
-import com.android.contacts.interactions.ContactDeletionInteraction;
-
-import java.util.ArrayList;
-
-public class ContactDetailActivity extends ContactsActivity {
- private static final String TAG = "ContactDetailActivity";
-
- private Contact mContactData;
- private Uri mLookupUri;
-
- private ContactDetailLayoutController mContactDetailLayoutController;
- private ContactLoaderFragment mLoaderFragment;
-
- private Handler mHandler = new Handler();
-
- @Override
- protected void onCreate(Bundle savedState) {
- super.onCreate(savedState);
-
- setContentView(R.layout.contact_detail_activity);
-
- mContactDetailLayoutController = new ContactDetailLayoutController(this, savedState,
- getFragmentManager(), null, mContactDetailFragmentListener);
-
- // We want the UP affordance but no app icon.
- // Setting HOME_AS_UP, SHOW_TITLE and clearing SHOW_HOME does the trick.
- ActionBar actionBar = getActionBar();
- if (actionBar != null) {
- actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
- ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE
- | ActionBar.DISPLAY_SHOW_HOME);
- actionBar.setTitle("");
- }
- }
-
- @Override
- public void onAttachFragment(Fragment fragment) {
- if (fragment instanceof ContactLoaderFragment) {
- mLoaderFragment = (ContactLoaderFragment) fragment;
- mLoaderFragment.setListener(mLoaderFragmentListener);
- mLoaderFragment.loadUri(getIntent().getData());
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.star, menu);
- return true;
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- final MenuItem starredMenuItem = menu.findItem(R.id.menu_star);
- starredMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem item) {
- // Toggle "starred" state
- // Make sure there is a contact
- if (mLookupUri != null) {
- // Read the current starred value from the UI instead of using the last
- // loaded state. This allows rapid tapping without writing the same
- // value several times
- final boolean isStarred = starredMenuItem.isChecked();
-
- // To improve responsiveness, swap out the picture (and tag) in the UI already
- ContactDisplayUtils.configureStarredMenuItem(starredMenuItem,
- mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
- !isStarred);
-
- // Now perform the real save
- Intent intent = ContactSaveService.createSetStarredIntent(
- ContactDetailActivity.this, mLookupUri, !isStarred);
- ContactDetailActivity.this.startService(intent);
- }
- return true;
- }
- });
- // If there is contact data, update the starred state
- if (mContactData != null) {
- ContactDisplayUtils.configureStarredMenuItem(starredMenuItem,
- mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
- mContactData.getStarred());
- }
- return true;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- // First check if the {@link ContactLoaderFragment} can handle the key
- if (mLoaderFragment != null && mLoaderFragment.handleKeyDown(keyCode)) return true;
-
- // Otherwise find the correct fragment to handle the event
- FragmentKeyListener mCurrentFragment = mContactDetailLayoutController.getCurrentPage();
- if (mCurrentFragment != null && mCurrentFragment.handleKeyDown(keyCode)) return true;
-
- // In the last case, give the key event to the superclass.
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (mContactDetailLayoutController != null) {
- mContactDetailLayoutController.onSaveInstanceState(outState);
- }
- }
-
- private final ContactLoaderFragmentListener mLoaderFragmentListener =
- new ContactLoaderFragmentListener() {
- @Override
- public void onContactNotFound() {
- finish();
- }
-
- @Override
- public void onDetailsLoaded(final Contact result) {
- if (result == null) {
- return;
- }
- // Since {@link FragmentTransaction}s cannot be done in the onLoadFinished() of the
- // {@link LoaderCallbacks}, then post this {@link Runnable} to the {@link Handler}
- // on the main thread to execute later.
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // If the activity is destroyed (or will be destroyed soon), don't update the UI
- if (isFinishing()) {
- return;
- }
- mContactData = result;
- mLookupUri = result.getLookupUri();
- invalidateOptionsMenu();
- setupTitle();
- mContactDetailLayoutController.setContactData(mContactData);
- }
- });
- }
-
- @Override
- public void onEditRequested(Uri contactLookupUri) {
- Intent intent = new Intent(Intent.ACTION_EDIT, contactLookupUri);
- intent.putExtra(
- ContactEditorActivity.INTENT_KEY_FINISH_ACTIVITY_ON_SAVE_COMPLETED, true);
- // Don't finish the detail activity after launching the editor because when the
- // editor is done, we will still want to show the updated contact details using
- // this activity.
- startActivity(intent);
- }
-
- @Override
- public void onDeleteRequested(Uri contactUri) {
- ContactDeletionInteraction.start(ContactDetailActivity.this, contactUri, true);
- }
- };
-
- /**
- * Setup the activity title and subtitle with contact name and company.
- */
- private void setupTitle() {
- CharSequence displayName = ContactDisplayUtils.getDisplayName(this, mContactData);
- String company = ContactDisplayUtils.getCompany(this, mContactData);
-
- ActionBar actionBar = getActionBar();
- actionBar.setTitle(displayName);
- actionBar.setSubtitle(company);
-
- final StringBuilder talkback = new StringBuilder();
- if (!TextUtils.isEmpty(displayName)) {
- talkback.append(displayName);
- }
- if (!TextUtils.isEmpty(company)) {
- if (talkback.length() != 0) {
- talkback.append(", ");
- }
- talkback.append(company);
- }
-
- if (talkback.length() != 0) {
- AccessibilityManager accessibilityManager =
- (AccessibilityManager) this.getSystemService(Context.ACCESSIBILITY_SERVICE);
- if (accessibilityManager.isEnabled()) {
- View decorView = getWindow().getDecorView();
- decorView.setContentDescription(talkback);
- decorView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
- }
- }
- }
-
- private final ContactDetailFragment.Listener mContactDetailFragmentListener =
- new ContactDetailFragment.Listener() {
- @Override
- public void onItemClicked(Intent intent) {
- if (intent == null) {
- return;
- }
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "No activity found for intent: " + intent);
- }
- }
-
- @Override
- public void onCreateRawContactRequested(
- ArrayList<ContentValues> values, AccountWithDataSet account) {
- Toast.makeText(ContactDetailActivity.this, R.string.toast_making_personal_copy,
- Toast.LENGTH_LONG).show();
- Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
- ContactDetailActivity.this, values, account,
- ContactDetailActivity.class, Intent.ACTION_VIEW);
- startService(serviceIntent);
-
- }
- };
-
- /**
- * This interface should be implemented by {@link Fragment}s within this
- * activity so that the activity can determine whether the currently
- * displayed view is handling the key event or not.
- */
- public interface FragmentKeyListener {
- /**
- * Returns true if the key down event will be handled by the implementing class, or false
- * otherwise.
- */
- public boolean handleKeyDown(int keyCode);
- }
-}
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 261f8e128..363e45902 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -274,7 +274,7 @@ public class PeopleActivity extends ContactsActivity implements
}
if (mRequest.getActionCode() == ContactsRequest.ACTION_VIEW_CONTACT) {
- redirect = new Intent(this, ContactDetailActivity.class);
+ redirect = new Intent(this, QuickContactActivity.class);
redirect.setAction(Intent.ACTION_VIEW);
redirect.setData(mRequest.getContactUri());
startActivity(redirect);
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
deleted file mode 100644
index 50be0974b..000000000
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ /dev/null
@@ -1,2250 +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.contacts.detail;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.content.ComponentName;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Directory;
-import android.provider.ContactsContract.StatusUpdates;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.DragEvent;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnDragListener;
-import android.view.View.OnTouchListener;
-import android.view.ViewGroup;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.AdapterView;
-import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.BaseAdapter;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ListAdapter;
-import android.widget.ListPopupWindow;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.TypePrecedence;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.common.CallUtil;
-import com.android.contacts.common.ClipboardUtils;
-import com.android.contacts.common.Collapser.Collapsible;
-import com.android.contacts.common.ContactPresenceIconUtil;
-import com.android.contacts.common.ContactsUtils;
-import com.android.contacts.common.GroupMetaData;
-import com.android.contacts.common.MoreContactUtils;
-import com.android.contacts.common.editor.SelectAccountDialogFragment;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.RawContact;
-import com.android.contacts.common.model.RawContactDelta;
-import com.android.contacts.common.model.RawContactDeltaList;
-import com.android.contacts.common.model.RawContactModifier;
-import com.android.contacts.common.model.ValuesDelta;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.common.model.account.AccountType.EditType;
-import com.android.contacts.common.model.account.AccountWithDataSet;
-import com.android.contacts.common.model.dataitem.DataItem;
-import com.android.contacts.common.model.dataitem.DataKind;
-import com.android.contacts.common.model.dataitem.EmailDataItem;
-import com.android.contacts.common.model.dataitem.EventDataItem;
-import com.android.contacts.common.model.dataitem.GroupMembershipDataItem;
-import com.android.contacts.common.model.dataitem.ImDataItem;
-import com.android.contacts.common.model.dataitem.NicknameDataItem;
-import com.android.contacts.common.model.dataitem.NoteDataItem;
-import com.android.contacts.common.model.dataitem.OrganizationDataItem;
-import com.android.contacts.common.model.dataitem.PhoneDataItem;
-import com.android.contacts.common.model.dataitem.RelationDataItem;
-import com.android.contacts.common.model.dataitem.SipAddressDataItem;
-import com.android.contacts.common.model.dataitem.StructuredNameDataItem;
-import com.android.contacts.common.model.dataitem.StructuredPostalDataItem;
-import com.android.contacts.common.model.dataitem.WebsiteDataItem;
-import com.android.contacts.common.util.AccountsListAdapter.AccountListFilter;
-import com.android.contacts.common.util.DataStatus;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.android.contacts.util.StructuredPostalUtils;
-import com.android.contacts.util.UiClosables;
-import com.google.common.base.Objects;
-import com.google.common.collect.Iterables;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ContactDetailFragment extends Fragment implements FragmentKeyListener,
- SelectAccountDialogFragment.Listener, OnItemClickListener {
-
- private static final String TAG = "ContactDetailFragment";
-
- private static final int TEXT_DIRECTION_UNDEFINED = -1;
-
- private interface ContextMenuIds {
- static final int COPY_TEXT = 0;
- static final int CLEAR_DEFAULT = 1;
- static final int SET_DEFAULT = 2;
- }
-
- private static final String KEY_CONTACT_URI = "contactUri";
- private static final String KEY_LIST_STATE = "liststate";
-
- private Context mContext;
- private View mView;
- private OnScrollListener mVerticalScrollListener;
- private Uri mLookupUri;
- private Listener mListener;
-
- private Contact mContactData;
- private ViewGroup mStaticPhotoContainer;
- private View mPhotoTouchOverlay;
- private ListView mListView;
- private ViewAdapter mAdapter;
- private Uri mPrimaryPhoneUri = null;
- private ViewEntryDimensions mViewEntryDimensions;
-
- private final ContactDetailPhotoSetter mPhotoSetter = new ContactDetailPhotoSetter();
-
- private Button mQuickFixButton;
- private QuickFix mQuickFix;
- private boolean mShowStaticPhoto = true;
-
- private final QuickFix[] mPotentialQuickFixes = new QuickFix[] {
- new MakeLocalCopyQuickFix(),
- new AddToMyContactsQuickFix()
- };
-
- /**
- * The view shown if the detail list is empty.
- * We set this to the list view when first bind the adapter, so that it won't be shown while
- * we're loading data.
- */
- private View mEmptyView;
-
- /**
- * Saved state of the {@link ListView}. This must be saved and applied to the {@ListView} only
- * when the adapter has been populated again.
- */
- private Parcelable mListState;
-
- /**
- * Lists of specific types of entries to be shown in contact details.
- */
- private ArrayList<DetailViewEntry> mPhoneEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mSmsEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mEmailEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mPostalEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mImEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mNicknameEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mGroupEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mRelationEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mNoteEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mWebsiteEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mSipEntries = new ArrayList<DetailViewEntry>();
- private ArrayList<DetailViewEntry> mEventEntries = new ArrayList<DetailViewEntry>();
- private final Map<AccountType, List<DetailViewEntry>> mOtherEntriesMap =
- new HashMap<AccountType, List<DetailViewEntry>>();
- private ArrayList<ViewEntry> mAllEntries = new ArrayList<ViewEntry>();
- private LayoutInflater mInflater;
-
- private boolean mIsUniqueNumber;
- private boolean mIsUniqueEmail;
-
- private ListPopupWindow mPopup;
-
- /**
- * This is to forward touch events to the list view to enable users to scroll the list view
- * from the blank area underneath the static photo when the layout with static photo is used.
- */
- private OnTouchListener mForwardTouchToListView = new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (mListView != null) {
- mListView.dispatchTouchEvent(event);
- return true;
- }
- return false;
- }
- };
-
- /**
- * This is to forward drag events to the list view to enable users to scroll the list view
- * from the blank area underneath the static photo when the layout with static photo is used.
- */
- private OnDragListener mForwardDragToListView = new OnDragListener() {
- @Override
- public boolean onDrag(View v, DragEvent event) {
- if (mListView != null) {
- mListView.dispatchDragEvent(event);
- return true;
- }
- return false;
- }
- };
-
- public ContactDetailFragment() {
- // Explicit constructor for inflation
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- mLookupUri = savedInstanceState.getParcelable(KEY_CONTACT_URI);
- mListState = savedInstanceState.getParcelable(KEY_LIST_STATE);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putParcelable(KEY_CONTACT_URI, mLookupUri);
- if (mListView != null) {
- outState.putParcelable(KEY_LIST_STATE, mListView.onSaveInstanceState());
- }
- }
-
- @Override
- public void onPause() {
- dismissPopupIfShown();
- super.onPause();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = activity;
- mViewEntryDimensions = new ViewEntryDimensions(mContext.getResources());
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- mView = inflater.inflate(R.layout.contact_detail_fragment, container, false);
- // Set the touch and drag listener to forward the event to the mListView so that
- // vertical scrolling can happen from outside of the list view.
- mView.setOnTouchListener(mForwardTouchToListView);
- mView.setOnDragListener(mForwardDragToListView);
-
- mInflater = inflater;
-
- mStaticPhotoContainer = (ViewGroup) mView.findViewById(R.id.static_photo_container);
- mPhotoTouchOverlay = mView.findViewById(R.id.photo_touch_intercept_overlay);
-
- mListView = (ListView) mView.findViewById(android.R.id.list);
- mListView.setOnItemClickListener(this);
- mListView.setItemsCanFocus(true);
- mListView.setOnScrollListener(mVerticalScrollListener);
-
- // Don't set it to mListView yet. We do so later when we bind the adapter.
- mEmptyView = mView.findViewById(android.R.id.empty);
-
- mQuickFixButton = (Button) mView.findViewById(R.id.contact_quick_fix);
- mQuickFixButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (mQuickFix != null) {
- mQuickFix.execute();
- }
- }
- });
-
- mView.setVisibility(View.INVISIBLE);
-
- if (mContactData != null) {
- bindData();
- }
-
- return mView;
- }
-
- public void setListener(Listener value) {
- mListener = value;
- }
-
- protected Context getContext() {
- return mContext;
- }
-
- protected Listener getListener() {
- return mListener;
- }
-
- protected Contact getContactData() {
- return mContactData;
- }
-
- public void setVerticalScrollListener(OnScrollListener listener) {
- mVerticalScrollListener = listener;
- }
-
- public Uri getUri() {
- return mLookupUri;
- }
-
- /**
- * Sets whether the static contact photo (that is not in a scrolling region), should be shown
- * or not.
- */
- public void setShowStaticPhoto(boolean showPhoto) {
- mShowStaticPhoto = showPhoto;
- }
-
- /**
- * Shows the contact detail with a message indicating there are no contact details.
- */
- public void showEmptyState() {
- setData(null, null);
- }
-
- public void setData(Uri lookupUri, Contact result) {
- mLookupUri = lookupUri;
- mContactData = result;
- bindData();
- }
-
- /**
- * Reset the list adapter in this {@link Fragment} to get rid of any saved scroll position
- * from a previous contact.
- */
- public void resetAdapter() {
- if (mListView != null) {
- mListView.setAdapter(mAdapter);
- }
- }
-
- /**
- * Returns the top coordinate of the first item in the {@link ListView}. If the first item
- * in the {@link ListView} is not visible or there are no children in the list, then return
- * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the
- * list cannot have a positive offset.
- */
- public int getFirstListItemOffset() {
- return ContactDisplayUtils.getFirstListItemOffset(mListView);
- }
-
- /**
- * Tries to scroll the first item to the given offset (this can be a no-op if the list is
- * already in the correct position).
- * @param offset which should be <= 0
- */
- public void requestToMoveToOffset(int offset) {
- ContactDisplayUtils.requestToMoveToOffset(mListView, offset);
- }
-
- protected void bindData() {
- if (mView == null) {
- return;
- }
-
- if (isAdded()) {
- getActivity().invalidateOptionsMenu();
- }
-
- if (mContactData == null) {
- mView.setVisibility(View.INVISIBLE);
- if (mStaticPhotoContainer != null) {
- mStaticPhotoContainer.setVisibility(View.GONE);
- }
- mAllEntries.clear();
- if (mAdapter != null) {
- mAdapter.notifyDataSetChanged();
- }
- return;
- }
-
- // Setup the photo if applicable
- if (mStaticPhotoContainer != null) {
- // The presence of a static photo container is not sufficient to determine whether or
- // not we should show the photo. Check the mShowStaticPhoto flag which can be set by an
- // outside class depending on screen size, layout, and whether the contact has social
- // updates or not.
- if (mShowStaticPhoto) {
- mStaticPhotoContainer.setVisibility(View.VISIBLE);
- final ImageView photoView = (ImageView) mStaticPhotoContainer.findViewById(
- R.id.photo);
- final boolean expandPhotoOnClick = mContactData.getPhotoUri() != null;
- final OnClickListener listener = mPhotoSetter.setupContactPhotoForClick(
- mContext, mContactData, photoView, expandPhotoOnClick);
- if (mPhotoTouchOverlay != null) {
- mPhotoTouchOverlay.setVisibility(View.VISIBLE);
- if (expandPhotoOnClick || mContactData.isWritableContact(mContext)) {
- mPhotoTouchOverlay.setOnClickListener(listener);
- } else {
- mPhotoTouchOverlay.setClickable(false);
- }
- }
- } else {
- mStaticPhotoContainer.setVisibility(View.GONE);
- }
- }
-
- // Build up the contact entries
- buildEntries();
-
- // Collapse similar data items for select {@link DataKind}s.
- /*Collapser.collapseList(mPhoneEntries);
- Collapser.collapseList(mSmsEntries);
- Collapser.collapseList(mEmailEntries);
- Collapser.collapseList(mPostalEntries);
- Collapser.collapseList(mImEntries);
- Collapser.collapseList(mEventEntries);
- Collapser.collapseList(mWebsiteEntries);*/
-
- mIsUniqueNumber = mPhoneEntries.size() == 1;
- mIsUniqueEmail = mEmailEntries.size() == 1;
-
- // Make one aggregated list of all entries for display to the user.
- setupFlattenedList();
-
- if (mAdapter == null) {
- mAdapter = new ViewAdapter();
- mListView.setAdapter(mAdapter);
- }
-
- // Restore {@link ListView} state if applicable because the adapter is now populated.
- if (mListState != null) {
- mListView.onRestoreInstanceState(mListState);
- mListState = null;
- }
-
- mAdapter.notifyDataSetChanged();
-
- mListView.setEmptyView(mEmptyView);
-
- configureQuickFix();
-
- mView.setVisibility(View.VISIBLE);
- }
-
- /*
- * Sets {@link #mQuickFix} to a useful action and configures the visibility of
- * {@link #mQuickFixButton}
- */
- private void configureQuickFix() {
- mQuickFix = null;
-
- for (QuickFix fix : mPotentialQuickFixes) {
- if (fix.isApplicable()) {
- mQuickFix = fix;
- break;
- }
- }
-
- // Configure the button
- if (mQuickFix == null) {
- mQuickFixButton.setVisibility(View.GONE);
- } else {
- mQuickFixButton.setVisibility(View.VISIBLE);
- mQuickFixButton.setText(mQuickFix.getTitle());
- }
- }
-
- /** @return default group id or -1 if no group or several groups are marked as default */
- private long getDefaultGroupId(List<GroupMetaData> groups) {
- long defaultGroupId = -1;
- for (GroupMetaData group : groups) {
- if (group.isDefaultGroup()) {
- // two default groups? return neither
- if (defaultGroupId != -1) return -1;
- defaultGroupId = group.getGroupId();
- }
- }
- return defaultGroupId;
- }
-
- /**
- * Build up the entries to display on the screen.
- */
- private final void buildEntries() {
- final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
- final ComponentName smsComponent = PhoneCapabilityTester.getSmsComponent(getContext());
- final boolean hasSms = (smsComponent != null);
- final boolean hasSip = PhoneCapabilityTester.isSipPhone(mContext);
-
- // Clear out the old entries
- mAllEntries.clear();
-
- mPrimaryPhoneUri = null;
-
- // Build up method entries
- if (mContactData == null) {
- return;
- }
-
- ArrayList<String> groups = new ArrayList<String>();
- for (RawContact rawContact: mContactData.getRawContacts()) {
- final long rawContactId = rawContact.getId();
- final AccountType accountType = rawContact.getAccountType(mContext);
- for (DataItem dataItem : rawContact.getDataItems()) {
- //dataItem.setRawContactId(rawContactId);
-
- //if (dataItem.getMimeType() == null) continue;
-
- if (dataItem instanceof GroupMembershipDataItem) {
- GroupMembershipDataItem groupMembership =
- (GroupMembershipDataItem) dataItem;
- Long groupId = groupMembership.getGroupRowId();
- if (groupId != null) {
- handleGroupMembership(groups, mContactData.getGroupMetaData(), groupId);
- }
- continue;
- }
-
- final DataKind kind = AccountTypeManager.getInstance(mContext)
- .getKindOrFallback(accountType, dataItem.getMimeType());
- if (kind == null) continue;
-
- final DetailViewEntry entry = DetailViewEntry.fromValues(mContext, dataItem,
- mContactData.isDirectoryEntry(), mContactData.getDirectoryId(), kind);
- entry.maxLines = kind.maxLinesForDisplay;
-
- final boolean hasData = !TextUtils.isEmpty(entry.data);
- final boolean isSuperPrimary = dataItem.isSuperPrimary();
-
- if (dataItem instanceof StructuredNameDataItem) {
- // Always ignore the name. It is shown in the header if set
- } else if (dataItem instanceof PhoneDataItem && hasData) {
- PhoneDataItem phone = (PhoneDataItem) dataItem;
- // Build phone entries
- entry.data = phone.getFormattedPhoneNumber();
- final Intent phoneIntent = hasPhone ?
- CallUtil.getCallIntent(entry.data) : null;
- Intent smsIntent = null;
- if (hasSms) {
- smsIntent = new Intent(Intent.ACTION_SENDTO,
- Uri.fromParts(CallUtil.SCHEME_SMSTO, entry.data, null));
- smsIntent.setComponent(smsComponent);
- }
-
- // Configure Icons and Intents.
- if (hasPhone && hasSms) {
- entry.intent = phoneIntent;
- entry.secondaryIntent = smsIntent;
- entry.secondaryActionIcon = kind.iconAltRes;
- entry.secondaryActionDescription =
- com.android.contacts.common.util.ContactDisplayUtils.
- getSmsLabelResourceId(entry.type);
- } else if (hasPhone) {
- entry.intent = phoneIntent;
- } else if (hasSms) {
- entry.intent = smsIntent;
- } else {
- entry.intent = null;
- }
-
- // Remember super-primary phone
- if (isSuperPrimary) mPrimaryPhoneUri = entry.uri;
-
- entry.isPrimary = isSuperPrimary;
-
- // If the entry is a primary entry, then render it first in the view.
- if (entry.isPrimary) {
- // add to beginning of list so that this phone number shows up first
- mPhoneEntries.add(0, entry);
- } else {
- // add to end of list
- mPhoneEntries.add(entry);
- }
-
- // Configure the text direction. Phone numbers should be displayed LTR
- // regardless of what locale the device is in.
- entry.textDirection = View.TEXT_DIRECTION_LTR;
- } else if (dataItem instanceof EmailDataItem && hasData) {
- // Build email entries
- entry.intent = new Intent(Intent.ACTION_SENDTO,
- Uri.fromParts(CallUtil.SCHEME_MAILTO, entry.data, null));
- entry.isPrimary = isSuperPrimary;
- // If entry is a primary entry, then render it first in the view.
- if (entry.isPrimary) {
- mEmailEntries.add(0, entry);
- } else {
- mEmailEntries.add(entry);
- }
-
- // When Email rows have status, create additional Im row
- final DataStatus status = mContactData.getStatuses().get(entry.id);
- if (status != null) {
- EmailDataItem email = (EmailDataItem) dataItem;
- ImDataItem im = ImDataItem.createFromEmail(email);
-
- final DetailViewEntry imEntry = DetailViewEntry.fromValues(mContext, im,
- mContactData.isDirectoryEntry(), mContactData.getDirectoryId(),
- kind);
- // buildImActions(mContext, imEntry, im);
- imEntry.setPresence(status.getPresence());
- imEntry.maxLines = kind.maxLinesForDisplay;
- mImEntries.add(imEntry);
- }
- } else if (dataItem instanceof StructuredPostalDataItem && hasData) {
- // Build postal entries
- entry.intent = StructuredPostalUtils.getViewPostalAddressIntent(entry.data);
- mPostalEntries.add(entry);
- } else if (dataItem instanceof ImDataItem && hasData) {
- // Build IM entries
- /*buildImActions(mContext, entry, (ImDataItem) dataItem);
-
- // Apply presence when available
- final DataStatus status = mContactData.getStatuses().get(entry.id);
- if (status != null) {
- entry.setPresence(status.getPresence());
- }
- mImEntries.add(entry);*/
- } else if (dataItem instanceof OrganizationDataItem) {
- // Organizations are not shown. The first one is shown in the header
- // and subsequent ones are not supported anymore
- } else if (dataItem instanceof NicknameDataItem && hasData) {
- // Build nickname entries
- /*final boolean isNameRawContact =
- (mContactData.getNameRawContactId() == rawContactId);
-
- final boolean duplicatesTitle =
- isNameRawContact
- && mContactData.getDisplayNameSource() == DisplayNameSources.NICKNAME;
-
- if (!duplicatesTitle) {
- entry.uri = null;
- mNicknameEntries.add(entry);
- }*/
- } else if (dataItem instanceof NoteDataItem && hasData) {
- // Build note entries
- // entry.uri = null;
- //mNoteEntries.add(entry);
- } else if (dataItem instanceof WebsiteDataItem && hasData) {
- // Build Website entries
- /*entry.uri = null;
- try {
- WebAddress webAddress = new WebAddress(entry.data);
- entry.intent = new Intent(Intent.ACTION_VIEW,
- Uri.parse(webAddress.toString()));
- } catch (ParseException e) {
- Log.e(TAG, "Couldn't parse website: " + entry.data);
- }
- mWebsiteEntries.add(entry);*/
- } else if (dataItem instanceof SipAddressDataItem && hasData) {
- // Build SipAddress entries
- /*entry.uri = null;
- if (hasSip) {
- entry.intent = CallUtil.getCallIntent(
- Uri.fromParts(CallUtil.SCHEME_SIP, entry.data, null));
- } else {
- entry.intent = null;
- }
- mSipEntries.add(entry);*/
- // TODO: Now that SipAddress is in its own list of entries
- // (instead of grouped in mOtherEntries), consider
- // repositioning it right under the phone number.
- // (Then, we'd also update FallbackAccountType.java to set
- // secondary=false for this field, and tweak the weight
- // of its DataKind.)
- } else if (dataItem instanceof EventDataItem && hasData) {
- /*final Calendar cal = DateUtils.parseDate(entry.data, false);
- if (cal != null) {
- final Date nextAnniversary =
- DateUtils.getNextAnnualDate(cal);
- final Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
- builder.appendPath("time");
- ContentUris.appendId(builder, nextAnniversary.getTime());
- entry.intent = new Intent(Intent.ACTION_VIEW).setData(builder.build());
- }
- entry.data = DateUtils.formatDate(mContext, entry.data);
- entry.uri = null;
- mEventEntries.add(entry);*/
- } else if (dataItem instanceof RelationDataItem && hasData) {
- /*entry.intent = new Intent(Intent.ACTION_SEARCH);
- entry.intent.putExtra(SearchManager.QUERY, entry.data);
- entry.intent.setType(Contacts.CONTENT_TYPE);
- mRelationEntries.add(entry);*/
- } else {
- // Handle showing custom rows
- entry.intent = new Intent(Intent.ACTION_VIEW);
- entry.intent.setDataAndType(entry.uri, entry.mimetype);
-
- entry.data = dataItem.buildDataString(getContext(), kind);
-
- if (!TextUtils.isEmpty(entry.data)) {
- // If the account type exists in the hash map, add it as another entry for
- // that account type
- if (mOtherEntriesMap.containsKey(accountType)) {
- List<DetailViewEntry> listEntries = mOtherEntriesMap.get(accountType);
- listEntries.add(entry);
- } else {
- // Otherwise create a new list with the entry and add it to the hash map
- List<DetailViewEntry> listEntries = new ArrayList<DetailViewEntry>();
- listEntries.add(entry);
- mOtherEntriesMap.put(accountType, listEntries);
- }
- }
- }
- }
- }
-
- if (!groups.isEmpty()) {
- DetailViewEntry entry = new DetailViewEntry();
- Collections.sort(groups);
- StringBuilder sb = new StringBuilder();
- int size = groups.size();
- for (int i = 0; i < size; i++) {
- if (i != 0) {
- sb.append(", ");
- }
- sb.append(groups.get(i));
- }
- entry.mimetype = GroupMembership.MIMETYPE;
- entry.kind = mContext.getString(R.string.groupsLabel);
- entry.data = sb.toString();
- mGroupEntries.add(entry);
- }
- }
-
- /**
- * Collapse all contact detail entries into one aggregated list with a {@link HeaderViewEntry}
- * at the top.
- */
- private void setupFlattenedList() {
- // All contacts should have a header view (even if there is no data for the contact).
- mAllEntries.add(new HeaderViewEntry());
-
- addPhoneticName();
-
- flattenList(mPhoneEntries);
- flattenList(mSmsEntries);
- flattenList(mEmailEntries);
- flattenList(mImEntries);
- flattenList(mNicknameEntries);
- flattenList(mWebsiteEntries);
-
- addNetworks();
-
- flattenList(mSipEntries);
- flattenList(mPostalEntries);
- flattenList(mEventEntries);
- flattenList(mGroupEntries);
- flattenList(mRelationEntries);
- flattenList(mNoteEntries);
- }
-
- /**
- * Add phonetic name (if applicable) to the aggregated list of contact details. This has to be
- * done manually because phonetic name doesn't have a mimetype or action intent.
- */
- private void addPhoneticName() {
- String phoneticName = ContactDisplayUtils.getPhoneticName(mContext, mContactData);
- if (TextUtils.isEmpty(phoneticName)) {
- return;
- }
-
- // Add a title
- String phoneticNameKindTitle = mContext.getString(R.string.name_phonetic);
- mAllEntries.add(new KindTitleViewEntry(phoneticNameKindTitle.toUpperCase()));
-
- // Add the phonetic name
- final DetailViewEntry entry = new DetailViewEntry();
- entry.kind = phoneticNameKindTitle;
- entry.data = phoneticName;
- mAllEntries.add(entry);
- }
-
- /**
- * Add attribution and other third-party entries (if applicable) under the "networks" section
- * of the aggregated list of contact details. This has to be done manually because the
- * attribution does not have a mimetype and the third-party entries don't have actually belong
- * to the same {@link DataKind}.
- */
- private void addNetworks() {
- String attribution = ContactDisplayUtils.getAttribution(mContext, mContactData);
- boolean hasAttribution = !TextUtils.isEmpty(attribution);
- int networksCount = mOtherEntriesMap.keySet().size();
-
- // Note: invitableCount will always be 0 for me profile. (ContactLoader won't set
- // invitable types for me profile.)
- int invitableCount = mContactData.getInvitableAccountTypes().size();
- if (!hasAttribution && networksCount == 0 && invitableCount == 0) {
- return;
- }
-
- // Add a title
- String networkKindTitle = mContext.getString(R.string.connections);
- mAllEntries.add(new KindTitleViewEntry(networkKindTitle.toUpperCase()));
-
- // Add the attribution if applicable
- if (hasAttribution) {
- final DetailViewEntry entry = new DetailViewEntry();
- entry.kind = networkKindTitle;
- entry.data = attribution;
- mAllEntries.add(entry);
-
- // Add a divider below the attribution if there are network details that will follow
- if (networksCount > 0) {
- mAllEntries.add(new SeparatorViewEntry());
- }
- }
-
- // Add the other entries from third parties
- for (AccountType accountType : mOtherEntriesMap.keySet()) {
-
- // Add a title for each third party app
- mAllEntries.add(new NetworkTitleViewEntry(mContext, accountType));
-
- for (DetailViewEntry detailEntry : mOtherEntriesMap.get(accountType)) {
- // Add indented separator
- SeparatorViewEntry separatorEntry = new SeparatorViewEntry();
- separatorEntry.setIsInSubSection(true);
- mAllEntries.add(separatorEntry);
-
- // Add indented detail
- detailEntry.setIsInSubSection(true);
- mAllEntries.add(detailEntry);
- }
- }
-
- mOtherEntriesMap.clear();
-
- // Add the "More networks" button, which opens the invitable account type list popup.
- if (invitableCount > 0) {
- addMoreNetworks();
- }
- }
-
- /**
- * Add the "More networks" entry. When clicked, show a popup containing a list of invitable
- * account types.
- */
- private void addMoreNetworks() {
- // First, prepare for the popup.
-
- // Adapter for the list popup.
- final InvitableAccountTypesAdapter popupAdapter = new InvitableAccountTypesAdapter(mContext,
- mContactData);
-
- // Listener called when a popup item is clicked.
- final AdapterView.OnItemClickListener popupItemListener
- = new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long id) {
- if (mListener != null && mContactData != null) {
- mListener.onItemClicked(MoreContactUtils.getInvitableIntent(
- popupAdapter.getItem(position) /* account type */,
- mContactData.getLookupUri()));
- }
- }
- };
-
- // Then create the click listener for the "More network" entry. Open the popup.
- View.OnClickListener onClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- showListPopup(v, popupAdapter, popupItemListener);
- }
- };
-
- // Finally create the entry.
- mAllEntries.add(new AddConnectionViewEntry(mContext, onClickListener));
- }
-
- /**
- * Iterate through {@link DetailViewEntry} in the given list and add it to a list of all
- * entries. Add a {@link KindTitleViewEntry} at the start if the length of the list is not 0.
- * Add {@link SeparatorViewEntry}s as dividers as appropriate. Clear the original list.
- */
- private void flattenList(ArrayList<DetailViewEntry> entries) {
- int count = entries.size();
-
- // Add a title for this kind by extracting the kind from the first entry
- if (count > 0) {
- String kind = entries.get(0).kind;
- mAllEntries.add(new KindTitleViewEntry(kind.toUpperCase()));
- }
-
- // Add all the data entries for this kind
- for (int i = 0; i < count; i++) {
- // For all entries except the first one, add a divider above the entry
- if (i != 0) {
- mAllEntries.add(new SeparatorViewEntry());
- }
- mAllEntries.add(entries.get(i));
- }
-
- // Clear old list because it's not needed anymore.
- entries.clear();
- }
-
- /**
- * Maps group ID to the corresponding group name, collapses all synonymous groups.
- * Ignores default groups (e.g. My Contacts) and favorites groups.
- */
- private void handleGroupMembership(
- ArrayList<String> groups, List<GroupMetaData> groupMetaData, long groupId) {
- if (groupMetaData == null) {
- return;
- }
-
- for (GroupMetaData group : groupMetaData) {
- if (group.getGroupId() == groupId) {
- if (!group.isDefaultGroup() && !group.isFavorites()) {
- String title = group.getTitle();
- if (!TextUtils.isEmpty(title) && !groups.contains(title)) {
- groups.add(title);
- }
- }
- break;
- }
- }
- }
-
- /**
- * Writes the Instant Messaging action into the given entry value.
- */
- /*@VisibleForTesting
- public static void buildImActions(Context context, DetailViewEntry entry,
- ImDataItem im) {
- final boolean isEmail = im.isCreatedFromEmail();
-
- if (!isEmail && !im.isProtocolValid()) {
- return;
- }
-
- final String data = im.getData();
- if (TextUtils.isEmpty(data)) {
- return;
- }
-
- final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK : im.getProtocol();
-
- if (protocol == Im.PROTOCOL_GOOGLE_TALK) {
- final int chatCapability = im.getChatCapability();
- entry.chatCapability = chatCapability;
- entry.typeString = Im.getProtocolLabel(context.getResources(), Im.PROTOCOL_GOOGLE_TALK,
- null).toString();
- if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
- entry.intent =
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
- entry.secondaryIntent =
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
- } else if ((chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
- // Allow Talking and Texting
- entry.intent =
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
- entry.secondaryIntent =
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?call"));
- } else {
- entry.intent =
- new Intent(Intent.ACTION_SENDTO, Uri.parse("xmpp:" + data + "?message"));
- }
- } else {
- // Build an IM Intent
- final Intent imIntent = getCustomIMIntent(im, protocol);
- if (imIntent != null &&
- PhoneCapabilityTester.isIntentRegistered(context, imIntent)) {
- entry.intent = imIntent;
- }
- }
- }*/
-
- /*@VisibleForTesting
- public static Intent getCustomIMIntent(ImDataItem im, int protocol) {
- String host = im.getCustomProtocol();
- final String data = im.getData();
- if (TextUtils.isEmpty(data)) {
- return null;
- }
- if (protocol != Im.PROTOCOL_CUSTOM) {
- // Try bringing in a well-known host for specific protocols
- host = ContactsUtils.lookupProviderNameFromId(protocol);
- }
- if (TextUtils.isEmpty(host)) {
- return null;
- }
- final String authority = host.toLowerCase();
- final Uri imUri = new Uri.Builder().scheme(CallUtil.SCHEME_IMTO).authority(
- authority).appendPath(data).build();
- final Intent intent = new Intent(Intent.ACTION_SENDTO, imUri);
- return intent;
- }*/
-
- /**
- * Show a list popup. Used for "popup-able" entry, such as "More networks".
- */
- private void showListPopup(View anchorView, ListAdapter adapter,
- final AdapterView.OnItemClickListener onItemClickListener) {
- dismissPopupIfShown();
- mPopup = new ListPopupWindow(mContext, null);
- mPopup.setAnchorView(anchorView);
- mPopup.setWidth(anchorView.getWidth());
- mPopup.setAdapter(adapter);
- mPopup.setModal(true);
-
- // We need to wrap the passed onItemClickListener here, so that we can dismiss() the
- // popup afterwards. Otherwise we could directly use the passed listener.
- mPopup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long id) {
- onItemClickListener.onItemClick(parent, view, position, id);
- dismissPopupIfShown();
- }
- });
- mPopup.show();
- }
-
- private void dismissPopupIfShown() {
- UiClosables.closeQuietly(mPopup);
- mPopup = null;
- }
-
- /**
- * Base class for an item in the {@link ViewAdapter} list of data, which is
- * supplied to the {@link ListView}.
- */
- static class ViewEntry {
- private final int viewTypeForAdapter;
- protected long id = -1;
- /** Whether or not the entry can be focused on or not. */
- protected boolean isEnabled = false;
-
- ViewEntry(int viewType) {
- viewTypeForAdapter = viewType;
- }
-
- int getViewType() {
- return viewTypeForAdapter;
- }
-
- long getId() {
- return id;
- }
-
- boolean isEnabled(){
- return isEnabled;
- }
-
- /**
- * Called when the entry is clicked. Only {@link #isEnabled} entries can get clicked.
- *
- * @param clickedView {@link View} that was clicked (Used, for example, as the anchor view
- * for a popup.)
- * @param fragmentListener {@link Listener} set to {@link ContactDetailFragment}
- */
- public void click(View clickedView, Listener fragmentListener) {
- }
- }
-
- /**
- * Header item in the {@link ViewAdapter} list of data.
- */
- private static class HeaderViewEntry extends ViewEntry {
-
- HeaderViewEntry() {
- super(ViewAdapter.VIEW_TYPE_HEADER_ENTRY);
- }
-
- }
-
- /**
- * Separator between items of the same {@link DataKind} in the
- * {@link ViewAdapter} list of data.
- */
- private static class SeparatorViewEntry extends ViewEntry {
-
- /**
- * Whether or not the entry is in a subsection (if true then the contents will be indented
- * to the right)
- */
- private boolean mIsInSubSection = false;
-
- SeparatorViewEntry() {
- super(ViewAdapter.VIEW_TYPE_SEPARATOR_ENTRY);
- }
-
- public void setIsInSubSection(boolean isInSubSection) {
- mIsInSubSection = isInSubSection;
- }
-
- public boolean isInSubSection() {
- return mIsInSubSection;
- }
- }
-
- /**
- * Title entry for items of the same {@link DataKind} in the
- * {@link ViewAdapter} list of data.
- */
- private static class KindTitleViewEntry extends ViewEntry {
-
- private final String mTitle;
-
- KindTitleViewEntry(String titleText) {
- super(ViewAdapter.VIEW_TYPE_KIND_TITLE_ENTRY);
- mTitle = titleText;
- }
-
- public String getTitle() {
- return mTitle;
- }
- }
-
- /**
- * A title for a section of contact details from a single 3rd party network.
- */
- private static class NetworkTitleViewEntry extends ViewEntry {
- private final Drawable mIcon;
- private final CharSequence mLabel;
-
- public NetworkTitleViewEntry(Context context, AccountType type) {
- super(ViewAdapter.VIEW_TYPE_NETWORK_TITLE_ENTRY);
- this.mIcon = type.getDisplayIcon(context);
- this.mLabel = type.getDisplayLabel(context);
- this.isEnabled = false;
- }
-
- public Drawable getIcon() {
- return mIcon;
- }
-
- public CharSequence getLabel() {
- return mLabel;
- }
- }
-
- /**
- * This is used for the "Add Connections" entry.
- */
- private static class AddConnectionViewEntry extends ViewEntry {
- private final Drawable mIcon;
- private final CharSequence mLabel;
- private final View.OnClickListener mOnClickListener;
-
- private AddConnectionViewEntry(Context context, View.OnClickListener onClickListener) {
- super(ViewAdapter.VIEW_TYPE_ADD_CONNECTION_ENTRY);
- this.mIcon = context.getResources().getDrawable(
- R.drawable.ic_menu_add_field_holo_light);
- this.mLabel = context.getString(R.string.add_connection_button);
- this.mOnClickListener = onClickListener;
- this.isEnabled = true;
- }
-
- @Override
- public void click(View clickedView, Listener fragmentListener) {
- if (mOnClickListener == null) return;
- mOnClickListener.onClick(clickedView);
- }
-
- public Drawable getIcon() {
- return mIcon;
- }
-
- public CharSequence getLabel() {
- return mLabel;
- }
- }
-
- /**
- * An item with a single detail for a contact in the {@link ViewAdapter}
- * list of data.
- */
- static class DetailViewEntry extends ViewEntry implements Collapsible<DetailViewEntry> {
- // TODO: Make getters/setters for these fields
- public int type = -1;
- public String kind;
- public String typeString;
- public String data;
- public Uri uri;
- public int maxLines = 1;
- public int textDirection = TEXT_DIRECTION_UNDEFINED;
- public String mimetype;
-
- public Context context = null;
- public boolean isPrimary = false;
- public int secondaryActionIcon = -1;
- public int secondaryActionDescription = -1;
- public Intent intent;
- public Intent secondaryIntent = null;
- public ArrayList<Long> ids = new ArrayList<Long>();
- public int collapseCount = 0;
-
- public int presence = -1;
- public int chatCapability = 0;
-
- private boolean mIsInSubSection = false;
-
- @Override
- public String toString() {
- return Objects.toStringHelper(this)
- .add("type", type)
- .add("kind", kind)
- .add("typeString", typeString)
- .add("data", data)
- .add("uri", uri)
- .add("maxLines", maxLines)
- .add("mimetype", mimetype)
- .add("context", context)
- .add("isPrimary", isPrimary)
- .add("secondaryActionIcon", secondaryActionIcon)
- .add("secondaryActionDescription", secondaryActionDescription)
- .add("intent", intent)
- .add("secondaryIntent", secondaryIntent)
- .add("ids", ids)
- .add("collapseCount", collapseCount)
- .add("presence", presence)
- .add("chatCapability", chatCapability)
- .add("mIsInSubSection", mIsInSubSection)
- .toString();
- }
-
- DetailViewEntry() {
- super(ViewAdapter.VIEW_TYPE_DETAIL_ENTRY);
- isEnabled = true;
- }
-
- /**
- * Build new {@link DetailViewEntry} and populate from the given values.
- */
- public static DetailViewEntry fromValues(Context context, DataItem item,
- boolean isDirectoryEntry, long directoryId, DataKind dataKind) {
- final DetailViewEntry entry = new DetailViewEntry();
- entry.id = item.getId();
- entry.context = context;
- entry.uri = ContentUris.withAppendedId(Data.CONTENT_URI, entry.id);
- if (isDirectoryEntry) {
- entry.uri = entry.uri.buildUpon().appendQueryParameter(
- ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
- }
- entry.mimetype = item.getMimeType();
- entry.kind = dataKind.getKindString(context);
- entry.data = item.buildDataString(context, dataKind);
-
- if (item.hasKindTypeColumn(dataKind)) {
- entry.type = item.getKindTypeColumn(dataKind);
-
- // get type string
- entry.typeString = "";
- for (EditType type : dataKind.typeList) {
- if (type.rawValue == entry.type) {
- if (type.customColumn == null) {
- // Non-custom type. Get its description from the resource
- entry.typeString = context.getString(type.labelRes);
- } else {
- // Custom type. Read it from the database
- entry.typeString =
- item.getContentValues().getAsString(type.customColumn);
- }
- break;
- }
- }
- } else {
- entry.typeString = "";
- }
-
- return entry;
- }
-
- public void setPresence(int presence) {
- this.presence = presence;
- }
-
- public void setIsInSubSection(boolean isInSubSection) {
- mIsInSubSection = isInSubSection;
- }
-
- public boolean isInSubSection() {
- return mIsInSubSection;
- }
-
- @Override
- public void collapseWith(DetailViewEntry entry) {
- // Choose the label associated with the highest type precedence.
- if (TypePrecedence.getTypePrecedence(mimetype, type)
- > TypePrecedence.getTypePrecedence(entry.mimetype, entry.type)) {
- type = entry.type;
- kind = entry.kind;
- typeString = entry.typeString;
- }
-
- // Choose the max of the maxLines and maxLabelLines values.
- maxLines = Math.max(maxLines, entry.maxLines);
-
- // Choose the presence with the highest precedence.
- if (StatusUpdates.getPresencePrecedence(presence)
- < StatusUpdates.getPresencePrecedence(entry.presence)) {
- presence = entry.presence;
- }
-
- // If any of the collapsed entries are primary make the whole thing primary.
- isPrimary = entry.isPrimary ? true : isPrimary;
-
- // uri, and contactdId, shouldn't make a difference. Just keep the original.
-
- // Keep track of all the ids that have been collapsed with this one.
- ids.add(entry.getId());
- collapseCount++;
- }
-
- @Override
- public boolean shouldCollapseWith(DetailViewEntry entry, Context context) {
- if (entry == null) {
- return false;
- }
-
- if (!MoreContactUtils.shouldCollapse(mimetype, data, entry.mimetype, entry.data)) {
- return false;
- }
-
- if (!TextUtils.equals(mimetype, entry.mimetype)
- || !ContactsUtils.areIntentActionEqual(intent, entry.intent)
- || !ContactsUtils.areIntentActionEqual(
- secondaryIntent, entry.secondaryIntent)) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public void click(View clickedView, Listener fragmentListener) {
- if (fragmentListener == null || intent == null) return;
- fragmentListener.onItemClicked(intent);
- }
- }
-
- /**
- * Cache of the children views for a view that displays a header view entry.
- */
- private static class HeaderViewCache {
- public final TextView displayNameView;
- public final TextView companyView;
- public final ImageView photoView;
- public final View photoOverlayView;
- public final ImageView starredView;
- public final int layoutResourceId;
-
- public HeaderViewCache(View view, int layoutResourceInflated) {
- displayNameView = (TextView) view.findViewById(R.id.name);
- companyView = (TextView) view.findViewById(R.id.company);
- photoView = (ImageView) view.findViewById(R.id.photo);
- photoOverlayView = view.findViewById(R.id.photo_touch_intercept_overlay);
- starredView = (ImageView) view.findViewById(R.id.star);
- layoutResourceId = layoutResourceInflated;
- }
-
- public void enablePhotoOverlay(OnClickListener listener) {
- if (photoOverlayView != null) {
- photoOverlayView.setOnClickListener(listener);
- photoOverlayView.setVisibility(View.VISIBLE);
- }
- }
- }
-
- private static class KindTitleViewCache {
- public final TextView titleView;
-
- public KindTitleViewCache(View view) {
- titleView = (TextView)view.findViewById(R.id.title);
- }
- }
-
- /**
- * Cache of the children views for a view that displays a {@link NetworkTitleViewEntry}
- */
- private static class NetworkTitleViewCache {
- public final TextView name;
- public final ImageView icon;
-
- public NetworkTitleViewCache(View view) {
- name = (TextView) view.findViewById(R.id.network_title);
- icon = (ImageView) view.findViewById(R.id.network_icon);
- }
- }
-
- /**
- * Cache of the children views for a view that displays a {@link AddConnectionViewEntry}
- */
- private static class AddConnectionViewCache {
- public final TextView name;
- public final ImageView icon;
- public final View primaryActionView;
-
- public AddConnectionViewCache(View view) {
- name = (TextView) view.findViewById(R.id.add_connection_label);
- icon = (ImageView) view.findViewById(R.id.add_connection_icon);
- primaryActionView = view.findViewById(R.id.primary_action_view);
- }
- }
-
- /**
- * Cache of the children views of a contact detail entry represented by a
- * {@link DetailViewEntry}
- */
- private static class DetailViewCache {
- public final TextView type;
- public final TextView data;
- public final ImageView presenceIcon;
- public final ImageView secondaryActionButton;
- public final View actionsViewContainer;
- public final View primaryActionView;
- public final View secondaryActionViewContainer;
- public final View secondaryActionDivider;
- public final View primaryIndicator;
-
- public DetailViewCache(View view,
- OnClickListener primaryActionClickListener,
- OnClickListener secondaryActionClickListener) {
- type = (TextView) view.findViewById(R.id.type);
- data = (TextView) view.findViewById(R.id.data);
- primaryIndicator = view.findViewById(R.id.primary_indicator);
- presenceIcon = (ImageView) view.findViewById(R.id.presence_icon);
-
- actionsViewContainer = view.findViewById(R.id.actions_view_container);
- actionsViewContainer.setOnClickListener(primaryActionClickListener);
- primaryActionView = view.findViewById(R.id.primary_action_view);
-
- secondaryActionViewContainer = view.findViewById(
- R.id.secondary_action_view_container);
- secondaryActionViewContainer.setOnClickListener(
- secondaryActionClickListener);
- secondaryActionButton = (ImageView) view.findViewById(
- R.id.secondary_action_button);
-
- secondaryActionDivider = view.findViewById(R.id.vertical_divider);
- }
- }
-
- private final class ViewAdapter extends BaseAdapter {
-
- public static final int VIEW_TYPE_DETAIL_ENTRY = 0;
- public static final int VIEW_TYPE_HEADER_ENTRY = 1;
- public static final int VIEW_TYPE_KIND_TITLE_ENTRY = 2;
- public static final int VIEW_TYPE_NETWORK_TITLE_ENTRY = 3;
- public static final int VIEW_TYPE_ADD_CONNECTION_ENTRY = 4;
- public static final int VIEW_TYPE_SEPARATOR_ENTRY = 5;
- private static final int VIEW_TYPE_COUNT = 6;
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- switch (getItemViewType(position)) {
- case VIEW_TYPE_HEADER_ENTRY:
- return getHeaderEntryView(convertView, parent);
- case VIEW_TYPE_SEPARATOR_ENTRY:
- return getSeparatorEntryView(position, convertView, parent);
- case VIEW_TYPE_KIND_TITLE_ENTRY:
- return getKindTitleEntryView(position, convertView, parent);
- case VIEW_TYPE_DETAIL_ENTRY:
- return getDetailEntryView(position, convertView, parent);
- case VIEW_TYPE_NETWORK_TITLE_ENTRY:
- return getNetworkTitleEntryView(position, convertView, parent);
- case VIEW_TYPE_ADD_CONNECTION_ENTRY:
- return getAddConnectionEntryView(position, convertView, parent);
- default:
- throw new IllegalStateException("Invalid view type ID " +
- getItemViewType(position));
- }
- }
-
- private View getHeaderEntryView(View convertView, ViewGroup parent) {
- final int desiredLayoutResourceId = R.layout.detail_header_contact_without_updates;
- View result = null;
- HeaderViewCache viewCache = null;
-
- // Only use convertView if it has the same layout resource ID as the one desired
- // (the two can be different on wide 2-pane screens where the detail fragment is reused
- // for many different contacts that do and do not have social updates).
- if (convertView != null) {
- viewCache = (HeaderViewCache) convertView.getTag();
- if (viewCache.layoutResourceId == desiredLayoutResourceId) {
- result = convertView;
- }
- }
-
- // Otherwise inflate a new header view and create a new view cache.
- if (result == null) {
- result = mInflater.inflate(desiredLayoutResourceId, parent, false);
- viewCache = new HeaderViewCache(result, desiredLayoutResourceId);
- result.setTag(viewCache);
- }
-
- ContactDisplayUtils.setDisplayName(mContext, mContactData,
- viewCache.displayNameView);
- ContactDisplayUtils.setCompanyName(mContext, mContactData, viewCache.companyView);
-
- // Set the photo if it should be displayed
- if (viewCache.photoView != null) {
- final boolean expandOnClick = mContactData.getPhotoUri() != null;
- final OnClickListener listener = mPhotoSetter.setupContactPhotoForClick(
- mContext, mContactData, viewCache.photoView, expandOnClick);
-
- if (expandOnClick || mContactData.isWritableContact(mContext)) {
- viewCache.enablePhotoOverlay(listener);
- }
- }
-
- // Set the starred state if it should be displayed
- final ImageView favoritesStar = viewCache.starredView;
- if (favoritesStar != null) {
- ContactDisplayUtils.configureStarredImageView(favoritesStar,
- mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
- mContactData.getStarred());
- final Uri lookupUri = mContactData.getLookupUri();
- favoritesStar.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // Toggle "starred" state
- // Make sure there is a contact
- if (lookupUri != null) {
- // Read the current starred value from the UI instead of using the last
- // loaded state. This allows rapid tapping without writing the same
- // value several times
- final Object tag = favoritesStar.getTag();
- final boolean isStarred = tag == null
- ? false : (Boolean) favoritesStar.getTag();
-
- // To improve responsiveness, swap out the picture (and tag) in the UI
- // already
- ContactDisplayUtils.configureStarredImageView(favoritesStar,
- mContactData.isDirectoryEntry(), mContactData.isUserProfile(),
- !isStarred);
-
- // Now perform the real save
- Intent intent = ContactSaveService.createSetStarredIntent(
- getContext(), lookupUri, !isStarred);
- getContext().startService(intent);
- }
- }
- });
- }
-
- return result;
- }
-
- private View getSeparatorEntryView(int position, View convertView, ViewGroup parent) {
- final SeparatorViewEntry entry = (SeparatorViewEntry) getItem(position);
- final View result = (convertView != null) ? convertView :
- mInflater.inflate(R.layout.contact_detail_separator_entry_view, parent, false);
-
- result.setPadding(entry.isInSubSection() ? mViewEntryDimensions.getWidePaddingLeft() :
- mViewEntryDimensions.getPaddingLeft(), 0,
- mViewEntryDimensions.getPaddingRight(), 0);
-
- return result;
- }
-
- private View getKindTitleEntryView(int position, View convertView, ViewGroup parent) {
- final KindTitleViewEntry entry = (KindTitleViewEntry) getItem(position);
- final View result;
- final KindTitleViewCache viewCache;
-
- if (convertView != null) {
- result = convertView;
- viewCache = (KindTitleViewCache)result.getTag();
- } else {
- result = mInflater.inflate(R.layout.list_separator, parent, false);
- viewCache = new KindTitleViewCache(result);
- result.setTag(viewCache);
- }
-
- viewCache.titleView.setText(entry.getTitle());
-
- return result;
- }
-
- private View getNetworkTitleEntryView(int position, View convertView, ViewGroup parent) {
- final NetworkTitleViewEntry entry = (NetworkTitleViewEntry) getItem(position);
- final View result;
- final NetworkTitleViewCache viewCache;
-
- if (convertView != null) {
- result = convertView;
- viewCache = (NetworkTitleViewCache) result.getTag();
- } else {
- result = mInflater.inflate(R.layout.contact_detail_network_title_entry_view,
- parent, false);
- viewCache = new NetworkTitleViewCache(result);
- result.setTag(viewCache);
- }
-
- viewCache.name.setText(entry.getLabel());
- viewCache.icon.setImageDrawable(entry.getIcon());
-
- return result;
- }
-
- private View getAddConnectionEntryView(int position, View convertView, ViewGroup parent) {
- final AddConnectionViewEntry entry = (AddConnectionViewEntry) getItem(position);
- final View result;
- final AddConnectionViewCache viewCache;
-
- if (convertView != null) {
- result = convertView;
- viewCache = (AddConnectionViewCache) result.getTag();
- } else {
- result = mInflater.inflate(R.layout.contact_detail_add_connection_entry_view,
- parent, false);
- viewCache = new AddConnectionViewCache(result);
- result.setTag(viewCache);
- }
- viewCache.name.setText(entry.getLabel());
- viewCache.icon.setImageDrawable(entry.getIcon());
- viewCache.primaryActionView.setOnClickListener(entry.mOnClickListener);
-
- return result;
- }
-
- private View getDetailEntryView(int position, View convertView, ViewGroup parent) {
- final DetailViewEntry entry = (DetailViewEntry) getItem(position);
- final View v;
- final DetailViewCache viewCache;
-
- // Check to see if we can reuse convertView
- if (convertView != null) {
- v = convertView;
- viewCache = (DetailViewCache) v.getTag();
- } else {
- // Create a new view if needed
- v = mInflater.inflate(R.layout.contact_detail_list_item, parent, false);
-
- // Cache the children
- viewCache = new DetailViewCache(v,
- mPrimaryActionClickListener, mSecondaryActionClickListener);
- v.setTag(viewCache);
- }
-
- bindDetailView(position, v, entry);
- return v;
- }
-
- private void bindDetailView(int position, View view, DetailViewEntry entry) {
- final Resources resources = mContext.getResources();
- DetailViewCache views = (DetailViewCache) view.getTag();
-
- if (!TextUtils.isEmpty(entry.typeString)) {
- views.type.setText(entry.typeString.toUpperCase());
- views.type.setVisibility(View.VISIBLE);
- } else {
- views.type.setVisibility(View.GONE);
- }
-
- views.data.setText(entry.data);
- setMaxLines(views.data, entry.maxLines);
-
- // Gray out the data item if it does not perform an action when clicked
- // Set primary_text_color even if it might have been set by default to avoid
- // views being gray sometimes when they are not supposed to, due to view reuse
- ((TextView) view.findViewById(R.id.data)).setTextColor(
- getResources().getColor((entry.intent == null) ?
- R.color.secondary_text_color : R.color.primary_text_color));
-
- // Set the default contact method
- views.primaryIndicator.setVisibility(entry.isPrimary ? View.VISIBLE : View.GONE);
-
- // Set the presence icon
- final Drawable presenceIcon = ContactPresenceIconUtil.getPresenceIcon(
- mContext, entry.presence);
- final ImageView presenceIconView = views.presenceIcon;
- if (presenceIcon != null) {
- presenceIconView.setImageDrawable(presenceIcon);
- presenceIconView.setVisibility(View.VISIBLE);
- } else {
- presenceIconView.setVisibility(View.GONE);
- }
-
- final ActionsViewContainer actionsButtonContainer =
- (ActionsViewContainer) views.actionsViewContainer;
- actionsButtonContainer.setTag(entry);
- actionsButtonContainer.setPosition(position);
- registerForContextMenu(actionsButtonContainer);
-
- // Set the secondary action button
- final ImageView secondaryActionView = views.secondaryActionButton;
- Drawable secondaryActionIcon = null;
- String secondaryActionDescription = null;
- if (entry.secondaryActionIcon != -1) {
- secondaryActionIcon = resources.getDrawable(entry.secondaryActionIcon);
- if (com.android.contacts.common.util.ContactDisplayUtils.isCustomPhoneType(
- entry.type)) {
- secondaryActionDescription = resources.getString(
- entry.secondaryActionDescription, entry.typeString);
- } else {
- secondaryActionDescription = resources.getString(
- entry.secondaryActionDescription);
- }
- } else if ((entry.chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
- secondaryActionIcon =
- resources.getDrawable(R.drawable.sym_action_videochat_holo_light);
- secondaryActionDescription = resources.getString(R.string.video_chat);
- } else if ((entry.chatCapability & Im.CAPABILITY_HAS_VOICE) != 0) {
- secondaryActionIcon =
- resources.getDrawable(R.drawable.sym_action_audiochat_holo_light);
- secondaryActionDescription = resources.getString(R.string.audio_chat);
- }
-
- final View secondaryActionViewContainer = views.secondaryActionViewContainer;
- if (entry.secondaryIntent != null && secondaryActionIcon != null) {
- secondaryActionView.setImageDrawable(secondaryActionIcon);
- secondaryActionView.setContentDescription(secondaryActionDescription);
- secondaryActionViewContainer.setTag(entry);
- secondaryActionViewContainer.setVisibility(View.VISIBLE);
- views.secondaryActionDivider.setVisibility(View.VISIBLE);
- } else {
- secondaryActionViewContainer.setVisibility(View.GONE);
- views.secondaryActionDivider.setVisibility(View.GONE);
- }
-
- // Right and left padding should not have "pressed" effect.
- view.setPadding(
- entry.isInSubSection()
- ? mViewEntryDimensions.getWidePaddingLeft()
- : mViewEntryDimensions.getPaddingLeft(),
- 0, mViewEntryDimensions.getPaddingRight(), 0);
- // Top and bottom padding should have "pressed" effect.
- final View primaryActionView = views.primaryActionView;
- primaryActionView.setPadding(
- primaryActionView.getPaddingLeft(),
- mViewEntryDimensions.getPaddingTop(),
- primaryActionView.getPaddingRight(),
- mViewEntryDimensions.getPaddingBottom());
- secondaryActionViewContainer.setPadding(
- secondaryActionViewContainer.getPaddingLeft(),
- mViewEntryDimensions.getPaddingTop(),
- secondaryActionViewContainer.getPaddingRight(),
- mViewEntryDimensions.getPaddingBottom());
-
- // Set the text direction
- if (entry.textDirection != TEXT_DIRECTION_UNDEFINED) {
- views.data.setTextDirection(entry.textDirection);
- }
- }
-
- private void setMaxLines(TextView textView, int maxLines) {
- if (maxLines == 1) {
- textView.setSingleLine(true);
- textView.setEllipsize(TextUtils.TruncateAt.END);
- } else {
- textView.setSingleLine(false);
- textView.setMaxLines(maxLines);
- textView.setEllipsize(null);
- }
- }
-
- private final OnClickListener mPrimaryActionClickListener = new OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mListener == null) return;
- final ViewEntry entry = (ViewEntry) view.getTag();
- if (entry == null) return;
- entry.click(view, mListener);
- }
- };
-
- private final OnClickListener mSecondaryActionClickListener = new OnClickListener() {
- @Override
- public void onClick(View view) {
- if (mListener == null) return;
- if (view == null) return;
- final ViewEntry entry = (ViewEntry) view.getTag();
- if (entry == null || !(entry instanceof DetailViewEntry)) return;
- final DetailViewEntry detailViewEntry = (DetailViewEntry) entry;
- final Intent intent = detailViewEntry.secondaryIntent;
- if (intent == null) return;
- mListener.onItemClicked(intent);
- }
- };
-
- @Override
- public int getCount() {
- return mAllEntries.size();
- }
-
- @Override
- public ViewEntry getItem(int position) {
- return mAllEntries.get(position);
- }
-
- @Override
- public int getItemViewType(int position) {
- return mAllEntries.get(position).getViewType();
- }
-
- @Override
- public int getViewTypeCount() {
- return VIEW_TYPE_COUNT;
- }
-
- @Override
- public long getItemId(int position) {
- final ViewEntry entry = mAllEntries.get(position);
- if (entry != null) {
- return entry.getId();
- }
- return -1;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- // Header will always be an item that is not enabled.
- return false;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return getItem(position).isEnabled();
- }
- }
-
- @Override
- public void onAccountSelectorCancelled() {
- }
-
- @Override
- public void onAccountChosen(AccountWithDataSet account, Bundle extraArgs) {
- createCopy(account);
- }
-
- private void createCopy(AccountWithDataSet account) {
- if (mListener != null) {
- mListener.onCreateRawContactRequested(mContactData.getContentValues(), account);
- }
- }
-
- /**
- * Default (fallback) list item click listener. Note the click event for DetailViewEntry is
- * caught by individual views in the list item view to distinguish the primary action and the
- * secondary action, so this method won't be invoked for that. (The listener is set in the
- * bindview in the adapter)
- * This listener is used for other kind of entries.
- */
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (mListener == null) return;
- final ViewEntry entry = mAdapter.getItem(position);
- if (entry == null) return;
- entry.click(view, mListener);
- }
-
- @Override
- public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, view, menuInfo);
-
- AdapterView.AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
- DetailViewEntry selectedEntry = (DetailViewEntry) mAllEntries.get(info.position);
-
- menu.setHeaderTitle(selectedEntry.data);
- menu.add(ContextMenu.NONE, ContextMenuIds.COPY_TEXT,
- ContextMenu.NONE, getString(R.string.copy_text));
-
- // Don't allow setting or clearing of defaults for directory contacts
- if (mContactData.isDirectoryEntry()) {
- return;
- }
-
- String selectedMimeType = selectedEntry.mimetype;
-
- // Defaults to true will only enable the detail to be copied to the clipboard.
- boolean isUniqueMimeType = true;
-
- // Only allow primary support for Phone and Email content types
- if (Phone.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
- isUniqueMimeType = mIsUniqueNumber;
- } else if (Email.CONTENT_ITEM_TYPE.equals(selectedMimeType)) {
- isUniqueMimeType = mIsUniqueEmail;
- }
-
- // Checking for previously set default
- if (selectedEntry.isPrimary) {
- menu.add(ContextMenu.NONE, ContextMenuIds.CLEAR_DEFAULT,
- ContextMenu.NONE, getString(R.string.clear_default));
- } else if (!isUniqueMimeType) {
- menu.add(ContextMenu.NONE, ContextMenuIds.SET_DEFAULT,
- ContextMenu.NONE, getString(R.string.set_default));
- }
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- AdapterView.AdapterContextMenuInfo menuInfo;
- try {
- menuInfo = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
- } catch (ClassCastException e) {
- Log.e(TAG, "bad menuInfo", e);
- return false;
- }
-
- switch (item.getItemId()) {
- case ContextMenuIds.COPY_TEXT:
- copyToClipboard(menuInfo.position);
- return true;
- case ContextMenuIds.SET_DEFAULT:
- setDefaultContactMethod(mListView.getItemIdAtPosition(menuInfo.position));
- return true;
- case ContextMenuIds.CLEAR_DEFAULT:
- clearDefaultContactMethod(mListView.getItemIdAtPosition(menuInfo.position));
- return true;
- default:
- throw new IllegalArgumentException("Unknown menu option " + item.getItemId());
- }
- }
-
- private void setDefaultContactMethod(long id) {
- Intent setIntent = ContactSaveService.createSetSuperPrimaryIntent(mContext, id);
- mContext.startService(setIntent);
- }
-
- private void clearDefaultContactMethod(long id) {
- Intent clearIntent = ContactSaveService.createClearPrimaryIntent(mContext, id);
- mContext.startService(clearIntent);
- }
-
- private void copyToClipboard(int viewEntryPosition) {
- // Getting the text to copied
- DetailViewEntry detailViewEntry = (DetailViewEntry) mAllEntries.get(viewEntryPosition);
- CharSequence textToCopy = detailViewEntry.data;
-
- // Checking for empty string
- if (TextUtils.isEmpty(textToCopy)) return;
-
- ClipboardUtils.copyText(getActivity(), detailViewEntry.typeString, textToCopy, true);
- }
-
- @Override
- public boolean handleKeyDown(int keyCode) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL: {
- TelephonyManager telephonyManager =
- (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
- if (telephonyManager != null &&
- telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
- // Skip out and let the key be handled at a higher level
- break;
- }
-
- int index = mListView.getSelectedItemPosition();
- if (index != -1) {
- final DetailViewEntry entry = (DetailViewEntry) mAdapter.getItem(index);
- if (entry != null && entry.intent != null &&
- entry.intent.getAction() == Intent.ACTION_CALL_PRIVILEGED) {
- mContext.startActivity(entry.intent);
- return true;
- }
- } else if (mPrimaryPhoneUri != null) {
- // There isn't anything selected, call the default number
- mContext.startActivity(CallUtil.getCallIntent(mPrimaryPhoneUri));
- return true;
- }
- return false;
- }
- }
-
- return false;
- }
-
- /**
- * Base class for QuickFixes. QuickFixes quickly fix issues with the Contact without
- * requiring the user to go to the editor. Example: Add to My Contacts.
- */
- private static abstract class QuickFix {
- public abstract boolean isApplicable();
- public abstract String getTitle();
- public abstract void execute();
- }
-
- private class AddToMyContactsQuickFix extends QuickFix {
- @Override
- public boolean isApplicable() {
- // Only local contacts
- if (mContactData == null || mContactData.isDirectoryEntry()) return false;
-
- // User profile cannot be added to contacts
- if (mContactData.isUserProfile()) return false;
-
- // Only if exactly one raw contact
- if (mContactData.getRawContacts().size() != 1) return false;
-
- // test if the default group is assigned
- final List<GroupMetaData> groups = mContactData.getGroupMetaData();
-
- // For accounts without group support, groups is null
- if (groups == null) return false;
-
- // remember the default group id. no default group? bail out early
- final long defaultGroupId = getDefaultGroupId(groups);
- if (defaultGroupId == -1) return false;
-
- final RawContact rawContact = mContactData.getRawContacts().get(0);
- final AccountType type = rawContact.getAccountType(getContext());
- // Offline or non-writeable account? Nothing to fix
- if (type == null || !type.areContactsWritable()) return false;
-
- // Check whether the contact is in the default group
- boolean isInDefaultGroup = false;
- for (DataItem dataItem : Iterables.filter(
- rawContact.getDataItems(), GroupMembershipDataItem.class)) {
- GroupMembershipDataItem groupMembership = (GroupMembershipDataItem) dataItem;
- final Long groupId = groupMembership.getGroupRowId();
- if (groupId != null && groupId == defaultGroupId) {
- isInDefaultGroup = true;
- break;
- }
- }
-
- return !isInDefaultGroup;
- }
-
- @Override
- public String getTitle() {
- return getString(R.string.add_to_my_contacts);
- }
-
- @Override
- public void execute() {
- final long defaultGroupId = getDefaultGroupId(mContactData.getGroupMetaData());
- // there should always be a default group (otherwise the button would be invisible),
- // but let's be safe here
- if (defaultGroupId == -1) return;
-
- // add the group membership to the current state
- final RawContactDeltaList contactDeltaList = mContactData.createRawContactDeltaList();
- final RawContactDelta rawContactEntityDelta = contactDeltaList.get(0);
-
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
- final AccountType type = rawContactEntityDelta.getAccountType(accountTypes);
- final DataKind groupMembershipKind = type.getKindForMimetype(
- GroupMembership.CONTENT_ITEM_TYPE);
- final ValuesDelta entry = RawContactModifier.insertChild(rawContactEntityDelta,
- groupMembershipKind);
- if (entry == null) return;
- entry.setGroupRowId(defaultGroupId);
-
- // and fire off the intent. we don't need a callback, as the database listener
- // should update the ui
- final Intent intent = ContactSaveService.createSaveContactIntent(getActivity(),
- contactDeltaList, "", 0, false, getActivity().getClass(),
- Intent.ACTION_VIEW, null);
- getActivity().startService(intent);
- }
- }
-
- private class MakeLocalCopyQuickFix extends QuickFix {
- @Override
- public boolean isApplicable() {
- // Not a directory contact? Nothing to fix here
- if (mContactData == null || !mContactData.isDirectoryEntry()) return false;
-
- // No export support? Too bad
- if (mContactData.getDirectoryExportSupport() == Directory.EXPORT_SUPPORT_NONE) {
- return false;
- }
-
- return true;
- }
-
- @Override
- public String getTitle() {
- return getString(R.string.menu_copyContact);
- }
-
- @Override
- public void execute() {
- if (mListener == null) {
- return;
- }
-
- int exportSupport = mContactData.getDirectoryExportSupport();
- switch (exportSupport) {
- case Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY: {
- createCopy(new AccountWithDataSet(mContactData.getDirectoryAccountName(),
- mContactData.getDirectoryAccountType(), null));
- break;
- }
- case Directory.EXPORT_SUPPORT_ANY_ACCOUNT: {
- final List<AccountWithDataSet> accounts =
- AccountTypeManager.getInstance(mContext).getAccounts(true);
- if (accounts.isEmpty()) {
- createCopy(null);
- return; // Don't show a dialog.
- }
-
- // In the common case of a single writable account, auto-select
- // it without showing a dialog.
- if (accounts.size() == 1) {
- createCopy(accounts.get(0));
- return; // Don't show a dialog.
- }
-
- SelectAccountDialogFragment.show(getFragmentManager(),
- ContactDetailFragment.this, R.string.dialog_new_contact_account,
- AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, null);
- break;
- }
- }
- }
- }
-
- /**
- * This class loads the correct padding values for a contact detail item so they can be applied
- * dynamically. For example, this supports the case where some detail items can be indented and
- * need extra padding.
- */
- private static class ViewEntryDimensions {
-
- private final int mWidePaddingLeft;
- private final int mPaddingLeft;
- private final int mPaddingRight;
- private final int mPaddingTop;
- private final int mPaddingBottom;
-
- public ViewEntryDimensions(Resources resources) {
- mPaddingLeft = resources.getDimensionPixelSize(
- R.dimen.detail_item_side_margin);
- mPaddingTop = resources.getDimensionPixelSize(
- R.dimen.detail_item_vertical_margin);
- mWidePaddingLeft = mPaddingLeft +
- resources.getDimensionPixelSize(R.dimen.detail_item_icon_margin) +
- resources.getDimensionPixelSize(R.dimen.detail_network_icon_size);
- mPaddingRight = mPaddingLeft;
- mPaddingBottom = mPaddingTop;
- }
-
- public int getWidePaddingLeft() {
- return mWidePaddingLeft;
- }
-
- public int getPaddingLeft() {
- return mPaddingLeft;
- }
-
- public int getPaddingRight() {
- return mPaddingRight;
- }
-
- public int getPaddingTop() {
- return mPaddingTop;
- }
-
- public int getPaddingBottom() {
- return mPaddingBottom;
- }
- }
-
- public static interface Listener {
- /**
- * User clicked a single item (e.g. mail). The intent passed in could be null.
- */
- public void onItemClicked(Intent intent);
-
- /**
- * User requested creation of a new contact with the specified values.
- *
- * @param values ContentValues containing data rows for the new contact.
- * @param account Account where the new contact should be created.
- */
- public void onCreateRawContactRequested(ArrayList<ContentValues> values,
- AccountWithDataSet account);
- }
-
- /**
- * Adapter for the invitable account types; used for the invitable account type list popup.
- */
- private final static class InvitableAccountTypesAdapter extends BaseAdapter {
- private final Context mContext;
- private final LayoutInflater mInflater;
- private final ArrayList<AccountType> mAccountTypes;
-
- public InvitableAccountTypesAdapter(Context context, Contact contactData) {
- mContext = context;
- mInflater = LayoutInflater.from(context);
- final List<AccountType> types = contactData.getInvitableAccountTypes();
- mAccountTypes = new ArrayList<AccountType>(types.size());
-
- for (int i = 0; i < types.size(); i++) {
- mAccountTypes.add(types.get(i));
- }
-
- Collections.sort(mAccountTypes, new AccountType.DisplayLabelComparator(mContext));
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final View resultView =
- (convertView != null) ? convertView
- : mInflater.inflate(R.layout.account_selector_list_item, parent, false);
-
- final TextView text1 = (TextView)resultView.findViewById(android.R.id.text1);
- final TextView text2 = (TextView)resultView.findViewById(android.R.id.text2);
- final ImageView icon = (ImageView)resultView.findViewById(android.R.id.icon);
-
- final AccountType accountType = mAccountTypes.get(position);
-
- CharSequence action = accountType.getInviteContactActionLabel(mContext);
- CharSequence label = accountType.getDisplayLabel(mContext);
- if (TextUtils.isEmpty(action)) {
- text1.setText(label);
- text2.setVisibility(View.GONE);
- } else {
- text1.setText(action);
- text2.setVisibility(View.VISIBLE);
- text2.setText(label);
- }
- icon.setImageDrawable(accountType.getDisplayIcon(mContext));
-
- return resultView;
- }
-
- @Override
- public int getCount() {
- return mAccountTypes.size();
- }
-
- @Override
- public AccountType getItem(int position) {
- return mAccountTypes.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
- }
-}
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
deleted file mode 100644
index d563baf2c..000000000
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2011 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.contacts.detail;
-
-import android.app.Activity;
-import android.app.FragmentManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-
-import com.android.contacts.R.id;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.util.UriUtils;
-
-/**
- * Sets ContactDetailFragment data and performs animations when data changes.
- *
- * TODO: rename, move some of this logic into ContactDetailFragment and/or delete this class. This
- * class used to have more responsibility: the ContactDetailFragment was used beside social update
- * Fragments.
- */
-public class ContactDetailLayoutController {
-
- private static final String KEY_CONTACT_URI = "contactUri";
-
- private final int SINGLE_PANE_FADE_IN_DURATION = 275;
-
- private final Activity mActivity;
- private final FragmentManager mFragmentManager;
- private final ContactDetailFragment.Listener mContactDetailFragmentListener;
- private final View mViewContainer;
-
- private ContactDetailFragment mDetailFragment;
- private Contact mContactData;
- private Uri mContactUri;
-
- public ContactDetailLayoutController(Activity activity, Bundle savedState,
- FragmentManager fragmentManager, View viewContainer,
- ContactDetailFragment.Listener contactDetailFragmentListener) {
-
- if (fragmentManager == null) {
- throw new IllegalStateException("Cannot initialize a ContactDetailLayoutController "
- + "without a non-null FragmentManager");
- }
-
- mActivity = activity;
- mFragmentManager = fragmentManager;
- mContactDetailFragmentListener = contactDetailFragmentListener;
- mViewContainer = viewContainer;
-
- initialize(savedState);
- }
-
- private void initialize(Bundle savedState) {
- mDetailFragment = (ContactDetailFragment) mFragmentManager
- .findFragmentById(id.contact_detail_about_fragment);
-
- mDetailFragment.setListener(mContactDetailFragmentListener);
-
- if (savedState != null) {
- mContactUri = savedState.getParcelable(KEY_CONTACT_URI);
-
- // Immediately setup layout since we have saved state
- showContact();
- }
- }
-
- public void setContactData(Contact data) {
- final boolean contactWasLoaded;
- final boolean isDifferentContact;
- if (mContactData == null) {
- contactWasLoaded = false;
- isDifferentContact = true;
- } else {
- contactWasLoaded = true;
- isDifferentContact =
- !UriUtils.areEqual(mContactData.getLookupUri(), data.getLookupUri());
- }
- mContactData = data;
-
- // Small screen: We are on our own screen. Fade the data in, but only the first time
- if (!contactWasLoaded) {
- mViewContainer.setAlpha(0.0f);
- final ViewPropertyAnimator animator = mViewContainer.animate();
- animator.alpha(1.0f);
- animator.setDuration(SINGLE_PANE_FADE_IN_DURATION);
- }
-
- showContact();
- }
-
- public void showEmptyState() {
- mDetailFragment.setShowStaticPhoto(false);
- mDetailFragment.showEmptyState();
- }
-
- private void showContact() {
- if (mContactData == null) {
- return;
- }
-
- Uri previousContactUri = mContactUri;
- mContactUri = mContactData.getLookupUri();
- boolean isDifferentContact = !UriUtils.areEqual(previousContactUri, mContactUri);
-
- mDetailFragment.setShowStaticPhoto(true);
-
- if (isDifferentContact) {
- mDetailFragment.resetAdapter();
- }
-
- mDetailFragment.setData(mContactUri, mContactData);
- }
-
- public FragmentKeyListener getCurrentPage() {
- return mDetailFragment;
- }
-
- public void onSaveInstanceState(Bundle outState) {
- outState.putParcelable(KEY_CONTACT_URI, mContactUri);
- }
-}
diff --git a/src/com/android/contacts/detail/ContactLoaderFragment.java b/src/com/android/contacts/detail/ContactLoaderFragment.java
deleted file mode 100644
index 1288cf7fe..000000000
--- a/src/com/android/contacts/detail/ContactLoaderFragment.java
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Copyright (C) 2011 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.contacts.detail;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.app.LoaderManager;
-import android.app.LoaderManager.LoaderCallbacks;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.content.Loader;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.Contacts;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toast;
-
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.common.list.ShortcutIntentBuilder;
-import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.ContactLoader;
-import com.android.contacts.util.PhoneCapabilityTester;
-import com.google.common.base.Objects;
-
-/**
- * This is an invisible worker {@link Fragment} that loads the contact details for the contact card.
- * The data is then passed to the listener, who can then pass the data to other {@link View}s.
- */
-public class ContactLoaderFragment extends Fragment implements FragmentKeyListener {
-
- private static final String TAG = ContactLoaderFragment.class.getSimpleName();
-
- /** The launch code when picking a ringtone */
- private static final int REQUEST_CODE_PICK_RINGTONE = 1;
-
- /** This is the Intent action to install a shortcut in the launcher. */
- private static final String ACTION_INSTALL_SHORTCUT =
- "com.android.launcher.action.INSTALL_SHORTCUT";
-
- private boolean mOptionsMenuOptions;
- private boolean mOptionsMenuEditable;
- private boolean mOptionsMenuShareable;
- private boolean mOptionsMenuCanCreateShortcut;
- private boolean mSendToVoicemailState;
- private String mCustomRingtone;
-
- /**
- * This is a listener to the {@link ContactLoaderFragment} and will be notified when the
- * contact details have finished loading or if the user selects any menu options.
- */
- public static interface ContactLoaderFragmentListener {
- /**
- * Contact was not found, so somehow close this fragment. This is raised after a contact
- * is removed via Menu/Delete
- */
- public void onContactNotFound();
-
- /**
- * Contact details have finished loading.
- */
- public void onDetailsLoaded(Contact result);
-
- /**
- * User decided to go to Edit-Mode
- */
- public void onEditRequested(Uri lookupUri);
-
- /**
- * User decided to delete the contact
- */
- public void onDeleteRequested(Uri lookupUri);
-
- }
-
- private static final int LOADER_DETAILS = 1;
-
- private static final String KEY_CONTACT_URI = "contactUri";
- private static final String LOADER_ARG_CONTACT_URI = "contactUri";
-
- private Context mContext;
- private Uri mLookupUri;
- private ContactLoaderFragmentListener mListener;
-
- private Contact mContactData;
-
- public ContactLoaderFragment() {
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null) {
- mLookupUri = savedInstanceState.getParcelable(KEY_CONTACT_URI);
- }
- }
-
- @Override
- public void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- outState.putParcelable(KEY_CONTACT_URI, mLookupUri);
- }
-
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- mContext = activity;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- setHasOptionsMenu(true);
- // This is an invisible view. This fragment is declared in a layout, so it can't be
- // "viewless". (i.e. can't return null here.)
- // See also the comment in the layout file.
- return inflater.inflate(R.layout.contact_detail_loader_fragment, container, false);
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- if (mLookupUri != null) {
- Bundle args = new Bundle();
- args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri);
- getLoaderManager().initLoader(LOADER_DETAILS, args, mDetailLoaderListener);
- }
- }
-
- public void loadUri(Uri lookupUri) {
- if (Objects.equal(lookupUri, mLookupUri)) {
- // Same URI, no need to load the data again
- return;
- }
-
- mLookupUri = lookupUri;
- if (mLookupUri == null) {
- getLoaderManager().destroyLoader(LOADER_DETAILS);
- mContactData = null;
- if (mListener != null) {
- mListener.onDetailsLoaded(mContactData);
- }
- } else if (getActivity() != null) {
- Bundle args = new Bundle();
- args.putParcelable(LOADER_ARG_CONTACT_URI, mLookupUri);
- getLoaderManager().restartLoader(LOADER_DETAILS, args, mDetailLoaderListener);
- }
- }
-
- public void setListener(ContactLoaderFragmentListener value) {
- mListener = value;
- }
-
- /**
- * The listener for the detail loader
- */
- private final LoaderManager.LoaderCallbacks<Contact> mDetailLoaderListener =
- new LoaderCallbacks<Contact>() {
- @Override
- public Loader<Contact> onCreateLoader(int id, Bundle args) {
- Uri lookupUri = args.getParcelable(LOADER_ARG_CONTACT_URI);
- return new ContactLoader(mContext, lookupUri, true /* loadGroupMetaData */,
- true /* load invitable account types */, true /* postViewNotification */,
- true /* computeFormattedPhoneNumber */);
- }
-
- @Override
- public void onLoadFinished(Loader<Contact> loader, Contact data) {
- if (!mLookupUri.equals(data.getRequestedUri())) {
- Log.e(TAG, "Different URI: requested=" + mLookupUri + " actual=" + data);
- return;
- }
-
- if (data.isError()) {
- // This shouldn't ever happen, so throw an exception. The {@link ContactLoader}
- // should log the actual exception.
- throw new IllegalStateException("Failed to load contact", data.getException());
- } else if (data.isNotFound()) {
- Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
- mContactData = null;
- } else {
- mContactData = data;
- }
-
- if (mListener != null) {
- if (mContactData == null) {
- mListener.onContactNotFound();
- } else {
- mListener.onDetailsLoaded(mContactData);
- }
- }
- // Make sure the options menu is setup correctly with the loaded data.
- if (getActivity() != null) getActivity().invalidateOptionsMenu();
- }
-
- @Override
- public void onLoaderReset(Loader<Contact> loader) {}
- };
-
- @Override
- public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
- inflater.inflate(R.menu.view_contact, menu);
- }
-
- public boolean isOptionsMenuChanged() {
- return mOptionsMenuOptions != isContactOptionsChangeEnabled()
- || mOptionsMenuEditable != isContactEditable()
- || mOptionsMenuShareable != isContactShareable()
- || mOptionsMenuCanCreateShortcut != isContactCanCreateShortcut();
- }
-
- @Override
- public void onPrepareOptionsMenu(Menu menu) {
- mOptionsMenuOptions = isContactOptionsChangeEnabled();
- mOptionsMenuEditable = isContactEditable();
- mOptionsMenuShareable = isContactShareable();
- mOptionsMenuCanCreateShortcut = isContactCanCreateShortcut();
- if (mContactData != null) {
- mSendToVoicemailState = mContactData.isSendToVoicemail();
- mCustomRingtone = mContactData.getCustomRingtone();
- }
-
- // Hide telephony-related settings (ringtone, send to voicemail)
- // if we don't have a telephone
- final MenuItem optionsSendToVoicemail = menu.findItem(R.id.menu_send_to_voicemail);
- if (optionsSendToVoicemail != null) {
- optionsSendToVoicemail.setChecked(mSendToVoicemailState);
- optionsSendToVoicemail.setVisible(mOptionsMenuOptions);
- }
- final MenuItem optionsRingtone = menu.findItem(R.id.menu_set_ringtone);
- if (optionsRingtone != null) {
- optionsRingtone.setVisible(mOptionsMenuOptions);
- }
-
- final MenuItem editMenu = menu.findItem(R.id.menu_edit);
- if (editMenu != null) {
- editMenu.setVisible(mOptionsMenuEditable);
- }
-
- final MenuItem deleteMenu = menu.findItem(R.id.menu_delete);
- if (deleteMenu != null) {
- deleteMenu.setVisible(mOptionsMenuEditable);
- }
-
- final MenuItem shareMenu = menu.findItem(R.id.menu_share);
- if (shareMenu != null) {
- shareMenu.setVisible(mOptionsMenuShareable);
- }
-
- final MenuItem createContactShortcutMenu = menu.findItem(R.id.menu_create_contact_shortcut);
- if (createContactShortcutMenu != null) {
- createContactShortcutMenu.setVisible(mOptionsMenuCanCreateShortcut);
- }
- }
-
- public boolean isContactOptionsChangeEnabled() {
- return mContactData != null && !mContactData.isDirectoryEntry()
- && PhoneCapabilityTester.isPhone(mContext);
- }
-
- public boolean isContactEditable() {
- return mContactData != null && !mContactData.isDirectoryEntry();
- }
-
- public boolean isContactShareable() {
- return mContactData != null && !mContactData.isDirectoryEntry();
- }
-
- public boolean isContactCanCreateShortcut() {
- return mContactData != null && !mContactData.isUserProfile()
- && !mContactData.isDirectoryEntry();
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_edit: {
- if (mListener != null) mListener.onEditRequested(mLookupUri);
- break;
- }
- case R.id.menu_delete: {
- if (mListener != null) mListener.onDeleteRequested(mLookupUri);
- return true;
- }
- case R.id.menu_set_ringtone: {
- if (mContactData == null) return false;
- doPickRingtone();
- return true;
- }
- case R.id.menu_share: {
- if (mContactData == null) return false;
-
- final String lookupKey = mContactData.getLookupKey();
- Uri shareUri = Uri.withAppendedPath(Contacts.CONTENT_VCARD_URI, lookupKey);
- if (mContactData.isUserProfile()) {
- // User is sharing the profile. We don't want to force the receiver to have
- // the highly-privileged READ_PROFILE permission, so we need to request a
- // pre-authorized URI from the provider.
- shareUri = getPreAuthorizedUri(shareUri);
- }
-
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(Contacts.CONTENT_VCARD_TYPE);
- intent.putExtra(Intent.EXTRA_STREAM, shareUri);
-
- // Launch chooser to share contact via
- final CharSequence chooseTitle = mContext.getText(R.string.share_via);
- final Intent chooseIntent = Intent.createChooser(intent, chooseTitle);
-
- try {
- mContext.startActivity(chooseIntent);
- } catch (ActivityNotFoundException ex) {
- Toast.makeText(mContext, R.string.share_error, Toast.LENGTH_SHORT).show();
- }
- return true;
- }
- case R.id.menu_send_to_voicemail: {
- // Update state and save
- mSendToVoicemailState = !mSendToVoicemailState;
- item.setChecked(mSendToVoicemailState);
- Intent intent = ContactSaveService.createSetSendToVoicemail(
- mContext, mLookupUri, mSendToVoicemailState);
- mContext.startService(intent);
- return true;
- }
- case R.id.menu_create_contact_shortcut: {
- // Create a launcher shortcut with this contact
- createLauncherShortcutWithContact();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Creates a launcher shortcut with the current contact.
- */
- private void createLauncherShortcutWithContact() {
- // Hold the parent activity of this fragment in case this fragment is destroyed
- // before the callback to onShortcutIntentCreated(...)
- final Activity parentActivity = getActivity();
-
- ShortcutIntentBuilder builder = new ShortcutIntentBuilder(parentActivity,
- new OnShortcutIntentCreatedListener() {
-
- @Override
- public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) {
- // Broadcast the shortcutIntent to the launcher to create a
- // shortcut to this contact
- shortcutIntent.setAction(ACTION_INSTALL_SHORTCUT);
- parentActivity.sendBroadcast(shortcutIntent);
-
- // Send a toast to give feedback to the user that a shortcut to this
- // contact was added to the launcher.
- Toast.makeText(parentActivity,
- R.string.createContactShortcutSuccessful,
- Toast.LENGTH_SHORT).show();
- }
-
- });
- builder.createContactShortcutIntent(mLookupUri);
- }
-
- /**
- * Calls into the contacts provider to get a pre-authorized version of the given URI.
- */
- private Uri getPreAuthorizedUri(Uri uri) {
- Bundle uriBundle = new Bundle();
- uriBundle.putParcelable(ContactsContract.Authorization.KEY_URI_TO_AUTHORIZE, uri);
- Bundle authResponse = mContext.getContentResolver().call(
- ContactsContract.AUTHORITY_URI,
- ContactsContract.Authorization.AUTHORIZATION_METHOD,
- null,
- uriBundle);
- if (authResponse != null) {
- return (Uri) authResponse.getParcelable(
- ContactsContract.Authorization.KEY_AUTHORIZED_URI);
- } else {
- return uri;
- }
- }
-
- @Override
- public boolean handleKeyDown(int keyCode) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DEL: {
- if (mListener != null) mListener.onDeleteRequested(mLookupUri);
- return true;
- }
- }
- return false;
- }
-
- private void doPickRingtone() {
-
- Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
- // Allow user to pick 'Default'
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
- // Show only ringtones
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);
- // Allow the user to pick a silent ringtone
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
-
- Uri ringtoneUri;
- if (mCustomRingtone != null) {
- ringtoneUri = Uri.parse(mCustomRingtone);
- } else {
- // Otherwise pick default ringtone Uri so that something is selected.
- ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
- }
-
- // Put checkmark next to the current ringtone for this contact
- intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, ringtoneUri);
-
- // Launch!
- try {
- startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE);
- } catch (ActivityNotFoundException ex) {
- Toast.makeText(mContext, R.string.missing_app, Toast.LENGTH_SHORT).show();
- }
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (resultCode != Activity.RESULT_OK) {
- return;
- }
-
- switch (requestCode) {
- case REQUEST_CODE_PICK_RINGTONE: {
- Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
- handleRingtonePicked(pickedUri);
- break;
- }
- }
- }
-
- private void handleRingtonePicked(Uri pickedUri) {
- if (pickedUri == null || RingtoneManager.isDefault(pickedUri)) {
- mCustomRingtone = null;
- } else {
- mCustomRingtone = pickedUri.toString();
- }
- Intent intent = ContactSaveService.createSetRingtone(
- mContext, mLookupUri, mCustomRingtone);
- mContext.startService(intent);
- }
-}
diff --git a/tests/src/com/android/contacts/ContactDetailTest.java b/tests/src/com/android/contacts/ContactDetailTest.java
deleted file mode 100644
index ea1e40e9d..000000000
--- a/tests/src/com/android/contacts/ContactDetailTest.java
+++ /dev/null
@@ -1,59 +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.contacts;
-
-import android.test.ActivityUnitTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import com.android.contacts.activities.ContactDetailActivity;
-import com.android.contacts.common.test.mocks.ContactsMockContext;
-import com.android.contacts.common.test.mocks.MockContentProvider;
-
-@SmallTest
-public class ContactDetailTest extends ActivityUnitTestCase<ContactDetailActivity> {
- private ContactsMockContext mContext;
- private MockContentProvider mContactsProvider;
-
- public ContactDetailTest() {
- super(ContactDetailActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mContext = new ContactsMockContext(getInstrumentation().getTargetContext());
- mContactsProvider = mContext.getContactsProvider();
- setActivityContext(mContext);
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
-// public void testFoo() {
-// // Use lookup-style Uris that also contain the Contact-ID
-// //long rawContactId1 = mCreator.createRawContact("JohnDoe", "John", "Doe");
-// //long contactId1 = mCreator.getContactIdByRawContactId(rawContactId1);
-// //Uri contactUri1 = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1);
-// Intent intent = new Intent(Intent.ACTION_VIEW,
-// ContentUris.withAppendedId(Contacts.CONTENT_URI, 123));
-// startActivity(intent, null, null);
-// ContactDetailActivity activity = getActivity();
-// mContactsProvider.verify();
-// }
-}
diff --git a/tests/src/com/android/contacts/activities/PeopleActivityTest.java b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
index 88585c56d..a9eac2076 100644
--- a/tests/src/com/android/contacts/activities/PeopleActivityTest.java
+++ b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
@@ -40,7 +40,6 @@ import com.android.contacts.common.testing.InjectedServices;
import com.android.contacts.common.test.mocks.ContactsMockContext;
import com.android.contacts.common.test.mocks.MockContentProvider;
import com.android.contacts.common.test.mocks.MockContentProvider.Query;
-import com.android.contacts.detail.ContactDetailFragment;
import com.android.contacts.interactions.TestLoaderManager;
import com.android.contacts.list.ContactBrowseListFragment;
import com.android.contacts.common.model.AccountTypeManager;