Merge change Ifaf19b53 into eclair
* changes:
More icons
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0950ff0..9242b1b 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -265,7 +265,9 @@
temporary hack until we add better framework support. -->
<activity
android:name=".ui.QuickContactActivity"
- android:theme="@style/FullyTranslucent.QuickContact">
+ android:theme="@style/FullyTranslucent.QuickContact"
+ android:launchMode="singleTop"
+ android:taskAffinity="android.task.fasttrack">
<intent-filter>
<action android:name="com.android.contacts.action.QUICK_CONTACT" />
@@ -338,7 +340,7 @@
<!-- Edit or insert details for a contact -->
<activity
android:name=".ui.EditContactActivity"
- android:theme="@style/TallTitleBarTheme"
+ android:label="@string/editContactDescription"
android:windowSoftInputMode="stateVisible|adjustResize">
<intent-filter android:label="@string/editContactDescription">
diff --git a/res/drawable-hdpi-finger/divider_dark_opaque.9.png b/res/drawable-hdpi-finger/divider_dark_opaque.9.png
new file mode 100644
index 0000000..9444f0d
--- /dev/null
+++ b/res/drawable-hdpi-finger/divider_dark_opaque.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/divider_vertical_dark.9.png b/res/drawable-hdpi-finger/divider_vertical_dark.9.png
index 30a68d0..702b878 100644
--- a/res/drawable-hdpi-finger/divider_vertical_dark.9.png
+++ b/res/drawable-hdpi-finger/divider_vertical_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_import_export.png b/res/drawable-hdpi-finger/ic_menu_import_export.png
similarity index 100%
rename from res/drawable-mdpi/ic_menu_import_export.png
rename to res/drawable-hdpi-finger/ic_menu_import_export.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/ic_menu_split.png b/res/drawable-hdpi-finger/ic_menu_split.png
new file mode 100644
index 0000000..33ef601
--- /dev/null
+++ b/res/drawable-hdpi-finger/ic_menu_split.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/infobar_dark.9.png b/res/drawable-hdpi-finger/infobar_dark.9.png
new file mode 100644
index 0000000..be0085a
--- /dev/null
+++ b/res/drawable-hdpi-finger/infobar_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/quickcontact_drop_shadow.9.png b/res/drawable-hdpi-finger/quickcontact_drop_shadow.9.png
index 5049903..6fafcbe 100644
--- a/res/drawable-hdpi-finger/quickcontact_drop_shadow.9.png
+++ b/res/drawable-hdpi-finger/quickcontact_drop_shadow.9.png
Binary files differ
diff --git a/res/drawable-hdpi-finger/section_dark.9.png b/res/drawable-hdpi-finger/section_dark.9.png
new file mode 100644
index 0000000..5a865fa
--- /dev/null
+++ b/res/drawable-hdpi-finger/section_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/divider_dark_opaque.9.png b/res/drawable-mdpi-finger/divider_dark_opaque.9.png
new file mode 100644
index 0000000..9444f0d
--- /dev/null
+++ b/res/drawable-mdpi-finger/divider_dark_opaque.9.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/divider_vertical_dark.9.png b/res/drawable-mdpi-finger/divider_vertical_dark.9.png
index 30a68d0..702b878 100644
--- a/res/drawable-mdpi-finger/divider_vertical_dark.9.png
+++ b/res/drawable-mdpi-finger/divider_vertical_dark.9.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_import_export.png b/res/drawable-mdpi-finger/ic_menu_import_export.png
similarity index 100%
rename from res/drawable-hdpi/ic_menu_import_export.png
rename to res/drawable-mdpi-finger/ic_menu_import_export.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/ic_menu_split.png b/res/drawable-mdpi-finger/ic_menu_split.png
new file mode 100644
index 0000000..9d69e4c
--- /dev/null
+++ b/res/drawable-mdpi-finger/ic_menu_split.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/infobar_dark.9.png b/res/drawable-mdpi-finger/infobar_dark.9.png
new file mode 100644
index 0000000..a3f3b01
--- /dev/null
+++ b/res/drawable-mdpi-finger/infobar_dark.9.png
Binary files differ
diff --git a/res/drawable-mdpi-finger/section_dark.9.png b/res/drawable-mdpi-finger/section_dark.9.png
new file mode 100644
index 0000000..dbf6ded
--- /dev/null
+++ b/res/drawable-mdpi-finger/section_dark.9.png
Binary files differ
diff --git a/res/layout-finger/contacts_list_item.xml b/res/layout-finger/contacts_list_item.xml
index 775e163..74f5bdd 100644
--- a/res/layout-finger/contacts_list_item.xml
+++ b/res/layout-finger/contacts_list_item.xml
@@ -24,7 +24,7 @@
>
<include
android:id="@+id/header"
- layout="@layout/list_separator"
+ layout="@layout/list_section"
/>
<RelativeLayout
diff --git a/res/layout-finger/contacts_list_item_photo.xml b/res/layout-finger/contacts_list_item_photo.xml
index f387502..bd3baf8 100644
--- a/res/layout-finger/contacts_list_item_photo.xml
+++ b/res/layout-finger/contacts_list_item_photo.xml
@@ -24,7 +24,7 @@
>
<include
android:id="@+id/header"
- layout="@layout/list_separator"
+ layout="@layout/list_section"
/>
<RelativeLayout
@@ -140,6 +140,6 @@
<View android:id="@+id/list_divider"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:background="@*android:drawable/divider_horizontal_dark_opaque"
+ android:background="@drawable/divider_dark_opaque"
/>
</LinearLayout>
diff --git a/res/layout-finger/list_section.xml b/res/layout-finger/list_section.xml
new file mode 100644
index 0000000..b91d213
--- /dev/null
+++ b/res/layout-finger/list_section.xml
@@ -0,0 +1,41 @@
+<?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.
+-->
+
+<!-- Layout used for list section separators. -->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="25dip"
+ android:background="@drawable/section_dark"
+ >
+ <TextView
+ android:id="@+id/header_text"
+ android:layout_width="56dip"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_alignParentLeft="true"
+ android:textStyle="bold"
+ android:textColor="#ffbfbfbf"
+ android:textSize="14sp"
+ android:gravity="center"
+ />
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_alignParentBottom="true"
+ android:background="@drawable/divider_dark_opaque"
+ />
+</RelativeLayout>
diff --git a/res/layout-finger/quickcontact.xml b/res/layout-finger/quickcontact.xml
index 33007f7..a2a94d4 100644
--- a/res/layout-finger/quickcontact.xml
+++ b/res/layout-finger/quickcontact.xml
@@ -24,7 +24,7 @@
android:id="@+id/header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="11dip">
+ android:layout_marginTop="10dip">
<ViewStub
android:id="@+id/header_small"
@@ -100,7 +100,7 @@
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
- android:layout_weight="1"
+ android:layout_weight="1"
android:background="@color/quickcontact_disambig"
android:divider="@drawable/quickcontact_disambig_divider"
android:cacheColorHint="@null" />
diff --git a/res/layout-finger/quickcontact_header_large.xml b/res/layout-finger/quickcontact_header_large.xml
index c94f1ad..df01f8a 100644
--- a/res/layout-finger/quickcontact_header_large.xml
+++ b/res/layout-finger/quickcontact_header_large.xml
@@ -24,11 +24,18 @@
android:gravity="center_vertical"
android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/photo"
+ android:layout_width="50dip"
+ android:layout_height="56dip"
+ android:layout_marginLeft="15dip"
+ android:layout_marginRight="15dip"
+ style="@*android:style/Widget.QuickContactBadge.WindowLarge" />
+
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:layout_marginLeft="8dip"
android:paddingRight="8dip"
android:orientation="vertical">
@@ -38,17 +45,29 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="end"
- android:textColor="#f000"
- android:textSize="14dip" />
+ android:textColor="@*android:color/primary_text_light"
+ android:textStyle="bold"
+ android:textSize="18dip" />
<TextView
android:id="@+id/status"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:maxLines="1"
+ android:singleLine="true"
android:ellipsize="end"
- android:textColor="#f999"
- android:textSize="12dip" />
+ android:textColor="@*android:color/secondary_text_light"
+ android:textSize="15dip"
+ android:layout_marginTop="-3dip" />
+
+ <TextView
+ android:id="@+id/timestamp"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@*android:color/secondary_text_light"
+ android:textSize="12dip"
+ android:layout_marginTop="-2dip" />
</LinearLayout>
diff --git a/res/layout-finger/quickcontact_header_med.xml b/res/layout-finger/quickcontact_header_med.xml
index 3533502..a5762fd 100644
--- a/res/layout-finger/quickcontact_header_med.xml
+++ b/res/layout-finger/quickcontact_header_med.xml
@@ -19,24 +19,42 @@
android:id="@+id/header_medium"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:minHeight="45dip"
+ android:minHeight="51dip"
android:background="@drawable/quickcontact_top_frame"
android:gravity="center_vertical"
android:orientation="horizontal">
- <TextView
- android:id="@+id/status"
+ <LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="15dip"
android:layout_marginRight="15dip"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="#f000"
- android:textSize="15dip" />
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@*android:color/primary_text_light"
+ android:textSize="15sp" />
+
+ <TextView
+ android:id="@+id/timestamp"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@*android:color/secondary_text_light"
+ android:textSize="12sp"
+ android:layout_marginTop="-2dip" />
+
+ </LinearLayout>
<ImageView
+ android:id="@+id/source_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="1dip"
@@ -44,8 +62,8 @@
<ImageView
android:id="@+id/source"
- android:layout_width="24dip"
- android:layout_height="24dip"
+ android:layout_width="30dip"
+ android:layout_height="30dip"
android:layout_marginLeft="13dip"
android:layout_marginRight="16dip"
android:scaleType="centerInside" />
diff --git a/res/layout-finger/total_contacts.xml b/res/layout-finger/total_contacts.xml
index ab15ce1..12badb6 100644
--- a/res/layout-finger/total_contacts.xml
+++ b/res/layout-finger/total_contacts.xml
@@ -17,12 +17,11 @@
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/totalContactsText"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- style="?android:attr/listSeparatorTextViewStyle"
- android:textColor="@*android:color/dim_foreground_dark"
- android:textSize="12sp"
+ android:layout_height="25dip"
+ android:textColor="#ffbfbfbf"
+ android:textSize="14sp"
android:textStyle="normal"
- android:background="@drawable/section_dark"
+ android:background="@drawable/infobar_dark"
android:paddingLeft="7dp"
- android:gravity="center|center_vertical"
+ android:gravity="center"
/>
\ No newline at end of file
diff --git a/res/layout/act_edit.xml b/res/layout/act_edit.xml
index 250a0e1..e56ec20 100644
--- a/res/layout/act_edit.xml
+++ b/res/layout/act_edit.xml
@@ -4,9 +4,9 @@
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.
@@ -14,60 +14,48 @@
limitations under the License.
-->
-<ScrollView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
- android:fillViewport="true">
+ android:orientation="vertical"
+>
+
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="1px"
+ android:layout_weight="1"
+ android:fillViewport="true"
+ >
+
+ <LinearLayout android:id="@+id/editors"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ />
+
+ </ScrollView>
<LinearLayout
- android:id="@+id/panel"
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:fillViewport="true">
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ style="@android:style/ButtonBar"
+ >
- <com.android.internal.widget.ContactHeaderWidget
- android:id="@+id/contact_header_widget"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
-
- <com.android.contacts.ScrollingTabWidget
- android:id="@+id/tab_widget"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
-
- <include
- android:id="@android:id/tabcontent"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:fillViewport="true"
- android:visibility="invisible"
- layout="@layout/item_contact_editor" />
-
- <LinearLayout
- android:layout_width="fill_parent"
+ <Button android:id="@+id/btn_done"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:orientation="horizontal"
- style="@android:style/ButtonBar">
+ android:layout_weight="1"
+ android:text="@string/menu_done"
+ />
- <Button
- android:id="@+id/btn_done"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/menu_done" />
-
- <Button
- android:id="@+id/btn_discard"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/menu_doNotSave" />
-
- </LinearLayout>
+ <Button android:id="@+id/btn_discard"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:text="@string/menu_doNotSave"
+ />
</LinearLayout>
-</ScrollView>
+</LinearLayout>
diff --git a/res/layout/item_contact_editor.xml b/res/layout/item_contact_editor.xml
index 24d612a..cea4bdb 100644
--- a/res/layout/item_contact_editor.xml
+++ b/res/layout/item_contact_editor.xml
@@ -18,76 +18,138 @@
<com.android.contacts.ui.widget.ContactEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:fillViewport="true">
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+>
- <TextView
- android:id="@+id/edit_read_only"
- android:layout_width="fill_parent"
+ <!-- Left side color bar -->
+ <ImageView
+ android:id="@+id/color_bar"
+ android:layout_width="15dip"
+ android:layout_height="fill_parent"
+ />
+
+ <!-- The content -->
+ <RelativeLayout
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:gravity="center|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:paddingTop="5dip"
- android:paddingBottom="5dip"
- android:text="@string/edit_read_only"/>
+ android:layout_weight="1"
+ >
- <FrameLayout
- android:id="@+id/stub_photo"
- android:layout_width="100dip"
- android:layout_height="96dip"
- android:layout_below="@id/edit_read_only"
- android:layout_alignWithParentIfMissing="true"
- android:paddingLeft="12dip"
- android:paddingTop="10dip">
+ <!-- Account info header -->
+ <RelativeLayout android:id="@+id/header"
+ android:layout_height="64dip"
+ android:layout_width="fill_parent"
+ >
+
+ <ImageView android:id="@+id/header_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="7dip"
+ android:layout_marginRight="7dip"
+ android:layout_centerVertical="true"
+ />
+
+ <TextView android:id="@+id/header_account_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/header_icon"
+ android:layout_alignTop="@id/header_icon"
+ android:layout_marginTop="-4dip"
+
+ android:textSize="24pt"
+ android:textStyle="bold"
+ android:textColor="?android:attr/textColorPrimary"
+ />
+
+ <TextView android:id="@+id/header_account_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toRightOf="@+id/header_icon"
+ android:layout_alignBottom="@+id/header_icon"
+ android:layout_marginBottom="2dip"
+
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ />
+
+ </RelativeLayout>
+
+ <FrameLayout
+ android:id="@+id/stub_photo"
+ android:layout_width="100dip"
+ android:layout_height="96dip"
+ android:layout_below="@id/header"
+ android:layout_alignWithParentIfMissing="true"
+ android:paddingLeft="12dip"
+ android:paddingTop="10dip">
+
+ <include
+ android:id="@+id/edit_photo"
+ layout="@layout/item_photo_editor" />
+
+ </FrameLayout>
<include
- android:id="@+id/edit_photo"
- layout="@layout/item_photo_editor" />
+ android:id="@+id/edit_name"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/stub_photo"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="4dip"
+ android:layout_alignWithParentIfMissing="true"
+ layout="@layout/item_generic_editor" />
- </FrameLayout>
+ <LinearLayout
+ android:id="@+id/sect_general"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/edit_name"
+ android:orientation="vertical"
+ />
- <include
- android:id="@+id/edit_name"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/edit_read_only"
- android:layout_toRightOf="@id/stub_photo"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip"
- android:layout_alignWithParentIfMissing="true"
- layout="@layout/item_generic_editor" />
+ <View android:id="@+id/head_secondary_divider"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/sect_general"
+ android:background="?android:attr/listDivider" />
- <LinearLayout
- android:id="@+id/sect_general"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/edit_name"
- android:orientation="vertical" />
+ <TextView
+ android:id="@+id/head_secondary"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/head_secondary_divider"
- <TextView
- android:id="@+id/head_secondary"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/sect_general"
- android:gravity="center_vertical"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:background="@color/sect_secondary"
- android:text="@string/edit_secondary_collapse"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/kind_title"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:focusable="true"
- android:clickable="true"
- android:paddingLeft="10dip"
- android:drawablePadding="10dip" />
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:text="@string/edit_secondary_collapse"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/kind_title"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:focusable="true"
+ android:clickable="true"
+ android:paddingLeft="10dip"
+ android:drawablePadding="10dip" />
- <LinearLayout
- android:id="@+id/sect_secondary"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@+id/head_secondary"
- android:background="@color/sect_secondary"
- android:orientation="vertical" />
+ <LinearLayout
+ android:id="@+id/sect_secondary"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/head_secondary"
+ android:orientation="vertical" />
+
+ <TextView
+ android:id="@+id/edit_read_only"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/edit_name"
+ android:gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:text="@string/edit_read_only"/>
+
+ </RelativeLayout>
</com.android.contacts.ui.widget.ContactEditorView>
diff --git a/res/layout/item_generic_editor.xml b/res/layout/item_generic_editor.xml
index 3c1426d..01fa980 100644
--- a/res/layout/item_generic_editor.xml
+++ b/res/layout/item_generic_editor.xml
@@ -16,7 +16,7 @@
<com.android.contacts.ui.widget.GenericEditorView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:paddingRight="?android:attr/scrollbarSize">
diff --git a/res/menu/edit.xml b/res/menu/edit.xml
index 658a567..6fafbcf 100644
--- a/res/menu/edit.xml
+++ b/res/menu/edit.xml
@@ -38,18 +38,8 @@
android:title="@string/menu_deleteContact" />
<item
- android:id="@+id/menu_photo_add"
- android:icon="@drawable/ic_menu_add_picture"
- android:title="@string/addPicture" />
-
- <item
- android:id="@+id/menu_photo_remove"
- android:icon="@android:drawable/ic_menu_delete"
- android:title="@string/removePicture" />
-
- <item
android:id="@+id/menu_split"
- android:icon="@drawable/ic_menu_merge"
+ android:icon="@drawable/ic_menu_split"
android:title="@string/menu_splitAggregate" />
<item
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 8372650..4f1b1ca 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -16,10 +16,10 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="contactsList" msgid="8661624236494819731">"Contactos"</string>
- <string name="launcherDialer" msgid="140610573639849799">"Marcador"</string>
+ <string name="launcherDialer" msgid="8636288196618486553">"Teléfono"</string>
<string name="shortcutContact" msgid="749243779392912958">"Contacto"</string>
- <string name="shortcutDialContact" msgid="7165340343023469996">"Marcado directo"</string>
- <string name="shortcutMessageContact" msgid="3025782962770298900">"Mensaje directo"</string>
+ <string name="shortcutDialContact" msgid="746622101599186779">"Marcado directo"</string>
+ <string name="shortcutMessageContact" msgid="2460337253595976198">"Mensaje directo"</string>
<string name="shortcutActivityTitle" msgid="6642877210643565436">"Seleccionar un acceso directo"</string>
<string name="callShortcutActivityTitle" msgid="6065749861423648991">"Seleccionar un número para la llamada"</string>
<string name="messageShortcutActivityTitle" msgid="3084542316620335911">"Seleccionar un número para el mensaje"</string>
@@ -40,10 +40,8 @@
<string name="menu_showBarcode" msgid="309973637178814132">"Mostrar código de barras"</string>
<string name="menu_editContact" msgid="3452858480713561396">"Editar contacto"</string>
<string name="menu_deleteContact" msgid="1916555454274101750">"Suprimir contacto"</string>
- <!-- no translation found for menu_call (3992595586042260618) -->
- <skip />
- <!-- no translation found for menu_sendSMS (5535886767547006515) -->
- <skip />
+ <string name="menu_call" msgid="3992595586042260618">"Llamar al contacto"</string>
+ <string name="menu_sendSMS" msgid="5535886767547006515">"Enviar texto al contacto"</string>
<string name="menu_sendEmail" msgid="7293508859242926187">"Enviar correo electrónico"</string>
<string name="menu_viewAddress" msgid="1814744325763202024">"Dirección del mapa"</string>
<string name="menu_makeDefaultNumber" msgid="4838759253316649534">"Crear número predeterminado"</string>
@@ -52,13 +50,27 @@
<string name="splitAggregate_title" msgid="2053462872948058798">"Dividir contacto"</string>
<string name="contactsSplitMessage" msgid="3439008547775199243">"División de contacto"</string>
<string name="menu_joinAggregate" msgid="5027981918265667970">"Unirse"</string>
+ <string name="menu_showSources" msgid="885215611438295455">"Mostrar fuentes"</string>
+ <string name="menu_hideSources" msgid="71367585820555477">"Ocultar fuentes"</string>
<string name="titleJoinAggregate" msgid="6970566008563147202">"Unirse al contacto"</string>
- <string name="separatorJoinAggregateSuggestions" msgid="5494823322479834017">"Sugerencias"</string>
+ <string name="titleJoinContactDataWith" msgid="7684875775798635354">"Unirse a contactos"</string>
+ <!-- no translation found for blurbJoinContactDataWith (995870557595050304) -->
+ <skip />
+ <!-- no translation found for showAllContactsJoinItem (2189695051430392383) -->
+ <skip />
+ <!-- no translation found for separatorJoinAggregateSuggestions (2831414448851313345) -->
+ <skip />
<string name="separatorJoinAggregateAll" msgid="7939932265026181043">"Todos los contactos"</string>
<string name="contactsJoinedMessage" msgid="7208148163607047389">"Unión de contactos"</string>
<string name="menu_contactOptions" msgid="1957061455705020617">"Opciones"</string>
<string name="contactOptionsTitle" msgid="8259347644090700915">"Opciones"</string>
<string name="deleteConfirmation_title" msgid="6394309508930335204">"Suprimir"</string>
+ <!-- no translation found for readOnlyContactWarning (1523906860865526049) -->
+ <skip />
+ <!-- no translation found for readOnlyContactDeleteConfirmation (56308694573221640) -->
+ <skip />
+ <!-- no translation found for multipleContactDeleteConfirmation (938900978442960800) -->
+ <skip />
<string name="deleteConfirmation" msgid="811706994761610640">"Este contacto se suprimirá."</string>
<string name="menu_done" msgid="796017761764190697">"Finalizado"</string>
<string name="menu_doNotSave" msgid="2174577548513895144">"Revertir"</string>
@@ -97,8 +109,8 @@
<string name="photoPickerNotFoundText" msgid="431331662154342581">"No hay imágenes disponibles en el teléfono."</string>
<string name="attachToContact" msgid="8820530304406066714">"Ícono de contacto"</string>
<string name="customLabelPickerTitle" msgid="1081475101983255212">"Nombre personalizado de etiqueta"</string>
- <string name="menu_displayGroup" msgid="6022511302986343108">"Mostrar grupos"</string>
- <string name="displayGroups" msgid="2645969886032719891">"Mostrar grupos"</string>
+ <string name="menu_displayGroup" msgid="5655505437727616553">"Mostrar opciones"</string>
+ <string name="displayGroups" msgid="2278964020773993336">"Mostrar opciones"</string>
<string name="syncGroupPreference" msgid="9028361137161162861">"Editar grupos sincroniz."</string>
<string name="importFromSim" msgid="8383900146531125319">"Importar contactos"</string>
<string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"Enviar llamadas directamente al correo de voz"</string>
@@ -107,6 +119,7 @@
<string name="addPicture" msgid="1594679312161537678">"Agregar ícono"</string>
<string name="removePicture" msgid="3041230993155966350">"Eliminar ícono"</string>
<string name="noContacts" msgid="8579310973261953559">"No hay contactos."</string>
+ <string name="noMatchingContacts" msgid="4266283206853990471">"No se encontraron contactos coincidentes."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"No hay contactos con números de teléfono."</string>
<string name="noFavorites" msgid="812766386743315815">"No hay favoritos."</string>
<string name="select_group_title" msgid="7955698611959835612">"Grupos"</string>
@@ -114,7 +127,7 @@
<string name="showAllGroups" msgid="5164410117611094297">"Todos los contactos"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Sólo contactos con teléfonos"</string>
<string name="showFilterPhonesDescrip" msgid="6644443248815191067">"Mostrar sólo contactos que posean números de teléfono"</string>
- <string name="headerContactGroups" msgid="1451383377487746789">"Grupos de contactos"</string>
+ <string name="headerContactGroups" msgid="2426134991932503843">"Elige contactos para mostrar"</string>
<plurals name="groupDescrip">
<item quantity="other" msgid="3507881585720628389">"<xliff:g id="COUNT">%0$d</xliff:g> contactos"</item>
</plurals>
@@ -122,16 +135,17 @@
<item quantity="other" msgid="3816047547470490208">"<xliff:g id="COUNT_0">%1$d</xliff:g> contactos, <xliff:g id="COUNTWITHPHONES">%2$d</xliff:g> con teléfonos"</item>
</plurals>
<string name="syncAllGroups" msgid="7512169081224806890">"Sincronizar todos los contactos"</string>
- <string name="groupNameMyContacts" msgid="5696566165170977126">"Mis contactos"</string>
+ <string name="groupNameMyContacts" msgid="277995505294105439">"Mis contactos"</string>
<string name="groupNameWithPhones" msgid="6981588604041120497">"Contactos con números de teléfono"</string>
<string name="starredInAndroid" msgid="6495527538140213440">"Marcado con asterisco en Android"</string>
+ <string name="savingContact" msgid="4075751076741924939">"Guardando contacto..."</string>
+ <string name="savingDisplayGroups" msgid="2133152192716475939">"Guardando opciones de visualización..."</string>
<string name="contactCreatedToast" msgid="8740102129968688060">"Contacto creado."</string>
<string name="contactSavedToast" msgid="7152589189385441091">"Contacto guardado."</string>
- <!-- no translation found for contactSavedErrorToast (9189098776225004666) -->
- <skip />
+ <string name="contactSavedErrorToast" msgid="9189098776225004666">"Error, no se han podido guardar las modificaciones de contacto."</string>
<string name="listSeparatorCallNumber" msgid="7115321894439629408">"Marcar número"</string>
<string name="listSeparatorCallNumber_edit" msgid="2999167270900823334">"Números de teléfono"</string>
- <string name="listSeparatorSendSmsMms" msgid="2480944736714739967">"Enviar SMS//MMS"</string>
+ <string name="listSeparatorSendSmsMms" msgid="5351657038532024412">"Enviar texto"</string>
<string name="listSeparatorSendEmail" msgid="5395590830304525721">"Enviar correo electrónico"</string>
<string name="listSeparatorSendEmail_edit" msgid="6859593624213634454">"Direcciones de correo electr."</string>
<string name="listSeparatorSendIm" msgid="2209260633185984105">"Enviar mensaje instantáneo"</string>
@@ -143,15 +157,17 @@
<string name="listSeparatorOtherInformation" msgid="7844959649638482329">"Otra información"</string>
<string name="listSeparatorOtherInformation_edit" msgid="1326921768011367750">"Otras opciones"</string>
<string name="listSeparatorMore_edit" msgid="858454837482243176">"Más"</string>
+ <string name="listTotalPhoneContacts" msgid="7371957507364352596">"<xliff:g id="NUM">%s</xliff:g> contactos con números de teléfono"</string>
+ <string name="listTotalAllContacts" msgid="4516547509985949443">"<xliff:g id="NUM">%s</xliff:g> contactos"</string>
<string name="socialStreamIconLabel" msgid="4367712449555075376">"Social"</string>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contactos"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritos"</string>
- <string name="dialerIconLabel" msgid="7228520966699542850">"Marcador"</string>
+ <string name="dialerIconLabel" msgid="6500826552823403796">"Teléfono"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Regist. de llam."</string>
<string name="liveFolderAll" msgid="4789010460767506206">"Todos los contactos"</string>
<string name="liveFolderFavorites" msgid="3100957542927222282">"Contactos marcados con asterisco"</string>
<string name="liveFolderPhone" msgid="3739376066610926780">"Contactos con números de teléfono"</string>
- <string name="menu_sendTextMessage" msgid="455561537582270625">"Enviar mensaje SMS"</string>
+ <string name="menu_sendTextMessage" msgid="6937343460284499306">"Enviar mensaje de texto"</string>
<string name="recentCalls_callNumber" msgid="1756372533999226126">"Llamar a <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="recentCalls_editNumberBeforeCall" msgid="7756171675833267857">"Editar número antes de llamar"</string>
<string name="recentCalls_addToContact" msgid="1429899535546487008">"Agregar a contactos"</string>
@@ -169,17 +185,13 @@
<string name="simContacts_emptyLoading" msgid="6700035985448642408">"Cargando desde tarjeta SIM..."</string>
<string name="simContacts_title" msgid="27341688347689769">"Contactos de tarjeta SIM"</string>
<string name="contactsSyncPlug" msgid="7248276704957313698"><font fgcolor="#ffffffff">"¡Sincroniza tus contactos de Google!"</font>" "\n" Luego de sincronizar tu teléfono, tus contactos estarán disponibles para ti dondequiera que vayas."</string>
- <string name="noContactsHelpText" msgid="2249195687463896364">"No tienes ningún contacto."\n\n"Para agregar contactos, presiona "<font fgcolor="#ffffffff"><b>"Menú"</b></font>" y selecciona:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Nuevo contacto"</b></font>" para crear un contacto nuevo desde cero"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importar contactos"</b></font>" para agregar contactos desde tu tarjeta SIM"\n</li></string>
- <!-- no translation found for noContactsHelpTextWithSync (2179024855526352215) -->
- <skip />
- <!-- no translation found for noContactsNoSimHelpText (645951808197910024) -->
- <skip />
- <!-- no translation found for noContactsNoSimHelpTextWithSync (511505839941079550) -->
- <skip />
- <!-- no translation found for noFavoritesHelpText (1705381563293866510) -->
- <skip />
+ <string name="noContactsHelpText" msgid="6788487368878712350">"No tienes ningún contacto para mostrar."\n\n"Para agregar contactos, presiona "<font fgcolor="#ffffffff"><b>"Menú"</b></font>" y toca:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Cuentas"</b></font>" para agregar o configurar una cuenta con contactos que puedes sincronizar en el teléfono"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Contacto nuevo"</b></font>" para crear tú mismo un contacto nuevo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importar/Exportar"</b></font>\n</li></string>
+ <string name="noContactsHelpTextWithSync" msgid="3734101165712848179">"No tienes ningún contacto para mostrar. (Si has agregado una cuenta, la sincronización de contactos puede demorar pocos minutos)."\n\n"Para agregar contactos, presiona "<font fgcolor="#ffffffff"><b>"Menú"</b></font>" y toca:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Cuentas"</b></font>" para agregar y configurar una cuenta con contactos que puedes sincronizar en el teléfono"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Mostrar opciones"</b></font>" para cambiar los contactos que sean visibles"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Contacto nuevo"</b></font>" para crear tú mismo un contacto nuevo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importar/Exportar"</b></font>\n</li></string>
+ <string name="noContactsNoSimHelpText" msgid="6553845386917463292">"No tienes ningún contacto para mostrar."\n\n"Para agregar contactos, presiona "<font fgcolor="#ffffffff"><b>"Menú"</b></font>" y toca:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Cuentas"</b></font>" para agregar o configurar una cuenta con contactos que puedes sincronizar en el teléfono"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Contacto nuevo"</b></font>" para crear tú mismo un contacto nuevo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importar/Exportar"</b></font>\n</li></string>
+ <string name="noContactsNoSimHelpTextWithSync" msgid="1122296298361373488">"No tienes ningún contacto para mostrar. (Si has agregado una cuenta, la sincronización de contactos puede demorar pocos minutos)."\n\n"Para agregar contactos, presiona "<font fgcolor="#ffffffff"><b>"Menú"</b></font>" y toca:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Cuentas"</b></font>" para agregar y configurar una cuenta con contactos que puedes sincronizar en el teléfono"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Mostrar opciones"</b></font>" para cambiar los contactos que sean visibles"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Contacto nuevo"</b></font>" para crear tú mismo un contacto nuevo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importar/Exportar"</b></font>\n</li></string>
+ <string name="noFavoritesHelpText" msgid="3744655776704833277">"No tienes ningún favorito."\n\n"Para agregar un contacto a tu lista de favoritos:"\n\n" "<li>"toca la pestaña "<b>"Contactos"</b>" "\n</li>" "\n<li>"toca el contacto que deseas agregar a tus favoritos"\n</li>" "\n<li>"toca el asterisco situado junto al nombre del contacto"\n</li></string>
<string name="seclectSyncGroups_title" msgid="1235432026231325655">"Seleccionar grupos para sincronizar"</string>
- <string name="liveFolder_all_label" msgid="1552523730090319259">"Todos los contactos"</string>
+ <string name="liveFolder_all_label" msgid="5961411940473276616">"Todos los contactos"</string>
<string name="liveFolder_favorites_label" msgid="2674341514070517105">"Marcado con asterisco"</string>
<string name="liveFolder_phones_label" msgid="1709786878793436245">"Teléfonos"</string>
<string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Usar teclado de tonos del teléfono"</string>
@@ -210,7 +222,7 @@
<string name="returnCall" msgid="8171961914203617813">"Regresar llamada"</string>
<string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> mins <xliff:g id="SECONDS">%s</xliff:g> s"</string>
<string name="favoritesFrquentSeparator" msgid="5007070838253932139">"Llamado con frecuencia"</string>
- <string name="add_contact_dlg_title" msgid="2789046541229846116">"Agregar contacto"</string>
+ <string name="add_contact_dlg_title" msgid="2896685845822146494">"Agregar contacto"</string>
<string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"¿Deseas agregar \"<xliff:g id="EMAIL">%s</xliff:g>\" a los contactos?"</string>
<string name="all_tab_label" msgid="4003124364397916826">"Todos"</string>
<string name="description_image_button_one" msgid="1740638037139856139">"uno"</string>
@@ -225,108 +237,125 @@
<string name="description_image_button_star" msgid="3365919907520767866">"asterisco"</string>
<string name="description_image_button_zero" msgid="4133108949401820710">"cero"</string>
<string name="description_image_button_pound" msgid="3039765597595889230">"libra"</string>
- <string name="no_sdcard_title" msgid="6455416795090113715">"No hay tarjeta SD"</string>
- <string name="no_sdcard_message" msgid="7791906118138538259">"No se ha detectado ninguna tarjeta SD"</string>
- <string name="searching_vcard_title" msgid="4158580043290687793">"Buscando VCard"</string>
+ <string name="no_sdcard_title" msgid="5911758680339949273">"No hay tarjeta SD"</string>
+ <string name="no_sdcard_message" msgid="6019391476490445358">"No se ha detectado ninguna tarjeta SD"</string>
+ <string name="searching_vcard_title" msgid="4970508055399376813">"Buscando vCard"</string>
<string name="select_import_type_title" msgid="2443742794103731022">"¿De dónde quieres importar contactos?"</string>
- <!-- no translation found for import_from_sim (3859272228033941659) -->
- <skip />
- <!-- no translation found for import_from_sdcard (8550360976693202816) -->
- <skip />
- <!-- no translation found for export_to_sdcard (2597105442616166277) -->
- <skip />
+ <string name="import_from_sim" msgid="3859272228033941659">"Importar de la tarjeta SIM"</string>
+ <string name="import_from_sdcard" msgid="8550360976693202816">"Importar de la tarjeta SD"</string>
+ <string name="export_to_sdcard" msgid="2597105442616166277">"Exportar a la tarjeta SD"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importar un archivo de vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importar múltiples archivos de vCard"</string>
<string name="import_all_vcard_string" msgid="5518136113853448474">"Importar todos los archivos de vCard"</string>
- <string name="searching_vcard_message" msgid="2467573749792455605">"Buscando datos VCard en VCard"</string>
- <string name="scanning_sdcard_failed_title" msgid="2788276113399585924">"No se ha podido explorar la Tarjeta SD"</string>
- <string name="scanning_sdcard_failed_message" msgid="925361244069058117">"No se ha podido explorar la Tarjeta SD"</string>
- <string name="fail_reason_io_error" msgid="5949038573678667996">"Error de E/S (Motivo: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
- <string name="fail_reason_vcard_parse_error" msgid="8877496734269540489">"No se ha podido analizar VCard por algún motivo inesperado"</string>
- <string name="fail_reason_vcard_not_supported_error" msgid="166568606246563552">"No se ha podido analizar VCard aunque el formato parece válido, ya que la implementación actual no lo admite"</string>
- <string name="fail_reason_no_vcard_file" msgid="1489638537002538332">"No se ha encontrado un archivo de VCard en la Tarjeta SD"</string>
- <string name="fail_reason_no_vcard_entry" msgid="3808734131680935043">"No se ha encontrado ninguna entrada válida de VCard para tu selección"</string>
+ <string name="searching_vcard_message" msgid="6917522333561434546">"Buscando datos de vCard en la tarjeta SD"</string>
+ <string name="scanning_sdcard_failed_title" msgid="3506782007953167180">"No se ha podido explorar la tarjeta SD"</string>
+ <!-- no translation found for scanning_sdcard_failed_message (3761992500690182922) -->
+ <skip />
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"Error de E/S"</string>
+ <string name="fail_reason_vcard_parse_error" msgid="1201233722762680214">"No se ha podido analizar vCard debido a un motivo inesperado"</string>
+ <string name="fail_reason_vcard_not_supported_error" msgid="655208100451286027">"No se ha podido analizar vCard aunque el formato parece válido, ya que la implementación actual no lo admite"</string>
+ <!-- no translation found for fail_reason_no_vcard_file (6376516175882881595) -->
+ <skip />
+ <string name="fail_reason_no_vcard_entry" msgid="4733290752474073143">"No se ha encontrado ninguna entrada válida de vCard para tu selección"</string>
<string name="fail_reason_failed_to_read_files" msgid="3659521123567134029">"No se pudieron importar uno o más archivos (%s)."</string>
- <string name="select_vcard_title" msgid="4615933643517710543">"Seleccionar archivo de VCard"</string>
- <string name="select_vcard_message" msgid="7028772212789057858">"Seleccionar un archivo de VCard para importar"</string>
+ <string name="fail_reason_unknown" msgid="999034019513096768">"Error desconocido"</string>
+ <string name="select_vcard_title" msgid="3968948173786172468">"Seleccionar archivo de vCard"</string>
+ <string name="select_vcard_message" msgid="221189184212818304">"Selecciona un archivo de vCard para importar"</string>
<string name="progress_shower_message" msgid="5636525578293752526">"Segmento <xliff:g id="ACTION">%s</xliff:g>"\n"<xliff:g id="FILENAME">%s</xliff:g>"</string>
- <string name="reading_vcard_title" msgid="430154704397375160">"Leyendo VCard"</string>
- <string name="reading_vcard_message" msgid="7470486051482460267">"Leyendo archivo(s) de VCard"</string>
- <string name="importing_vcard_message" msgid="2466665710812588738">"Importando datos VCard"</string>
- <string name="reading_vcard_failed_title" msgid="5042366466147724748">"No se han podido leer los datos VCard"</string>
- <string name="reading_vcard_failed_message" msgid="780588344175743735">"No se han podido leer los datos VCard"\n"Motivo: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="reading_vcard_title" msgid="4723433501579653199">"Leyendo vCard"</string>
+ <string name="reading_vcard_message" msgid="6381368920030748743">"Leyendo archivo(s) de vCard"</string>
+ <string name="importing_vcard_message" msgid="4046655384673753503">"Importando datos de vCard"</string>
+ <string name="reading_vcard_failed_title" msgid="4923008144735294994">"No se han podido leer los datos de vCard"</string>
+ <string name="reading_vcard_failed_message" msgid="5684089173948287107">"No se ha podido leer vCard."\n"Motivo: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
<string name="reading_vcard_contacts" msgid="3066834102042012868">"<xliff:g id="CURRENT_NUMBER">%s</xliff:g> de <xliff:g id="TOTAL_NUMBER">%s</xliff:g> contactos"</string>
<string name="reading_vcard_files" msgid="34180143726972661">"<xliff:g id="CURRENT_NUMBER">%s</xliff:g> de <xliff:g id="TOTAL_NUMBER">%s</xliff:g> archivos"</string>
+ <string name="export_all_contacts" msgid="2873892623335194071">"Todos los contactos"</string>
+ <string name="export_phone_local_only" msgid="3380497955409896761">"Contactos guardados localmente"</string>
<string name="export_contact_list" msgid="3165097742175874384">"Exportar contactos"</string>
- <string name="confirm_export_title" msgid="1693047909433122854">"Confirmación para exportar"</string>
- <string name="confirm_export_message" msgid="63482084706768079">"¿Aceptas exportar tu lista de contactos a \"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\"?"</string>
- <string name="exporting_contact_failed_title" msgid="1455264422455075858">"Ha ocurrido un error al exportar datos de contacto"</string>
- <string name="exporting_contact_failed_message" msgid="1426451081541603512">"Ha ocurrido un error al exportar los datos de contacto"\n"Motivo del error: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
- <string name="fail_reason_too_many_vcard" msgid="5416992255233341607">"Demasiados datos de VCard en la tarjeta SD"</string>
- <string name="fail_reason_too_long_filename" msgid="7105223965196949065">"Nombre de archivo demasiado largo (\"<xliff:g id="FILENAME">%s</xliff:g>\") es necesario"</string>
+ <string name="confirm_export_title" msgid="7648747763127442983">"Confirmar exportación"</string>
+ <string name="confirm_export_message" msgid="3875683519257829750">"¿Estás seguro de que deseas exportar tu lista de contactos a \"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\"?"</string>
+ <string name="exporting_contact_failed_title" msgid="585823094820602526">"No se han podido exportar los datos de contacto"</string>
+ <string name="exporting_contact_failed_message" msgid="4151348002470298092">"No se han podido exportar los datos de contacto."\n"Motivo: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_no_exportable_contact" msgid="4919714086648344495">"No hay ningún contacto exportable"</string>
+ <string name="fail_reason_too_many_vcard" msgid="7084146295639672658">"Demasiados archivos de vCard en la tarjeta SD"</string>
+ <string name="fail_reason_too_long_filename" msgid="1915716071321839166">"El nombre de archivo requerido es demasiado largo (\"<xliff:g id="FILENAME">%s</xliff:g>\")"</string>
<string name="fail_reason_cannot_open_destination_dir" msgid="1739293936432987758">"No se ha podido abrir o crear el directorio de destino \"<xliff:g id="DIR_NAME">%s</xliff:g>\""</string>
<string name="exporting_contact_list_title" msgid="9072240631534457415">"Exportando datos de contacto"</string>
<string name="exporting_contact_list_message" msgid="5640326540405486055">"Exportando datos de contacto a \"<xliff:g id="FILE_NAME">%s</xliff:g>\""</string>
<string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">"No se ha podido inicializar el exportador: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
<string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"Se produjo un error durante la exportación: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="composer_failed_to_get_database_infomation" msgid="3723109558155169053">"No se ha podido obtener información de la base de datos"</string>
+ <string name="composer_has_no_exportable_contact" msgid="2239503301380653777">"No hay ningún contacto exportable. Puedes elegir datos no exportables"</string>
+ <string name="composer_not_initialized" msgid="8041534450748388843">"El redactor de vCard no se ha inicializado correctamente"</string>
<string name="fail_reason_could_not_open_file" msgid="4013520943128739511">"No se pudo abrir \"<xliff:g id="FILE_NAME">%s</xliff:g>\": <xliff:g id="EXACT_REASON">%s</xliff:g>"</string>
<string name="exporting_contact_list_progress" msgid="560522409559101193">"<xliff:g id="CURRENT_NUMBER">%s</xliff:g> de <xliff:g id="TOTAL_NUMBER">%s</xliff:g> contactos"</string>
<string name="search_settings_description" msgid="2675223022992445813">"Nombres de tus contactos"</string>
- <string name="add_2sec_pause" msgid="1488865103809190124">"Agregar pausa de dos segundos"</string>
- <string name="add_wait" msgid="8347184715316058465">"Agregar espera"</string>
+ <string name="add_2sec_pause" msgid="9214012315201040129">"Agregar pausa de 2 segundos"</string>
+ <string name="add_wait" msgid="3360818652790319634">"Agregar espera"</string>
<string name="dial_button_label" msgid="7637725632722605863">"Marcar"</string>
- <!-- no translation found for call_disambig_title (1911302597959335178) -->
+ <string name="call_disambig_title" msgid="1911302597959335178">"Llamar con"</string>
+ <string name="sms_disambig_title" msgid="4675399294513152364">"Texto con"</string>
+ <string name="make_primary" msgid="5829291915305113983">"Recuerda esta opción"</string>
+ <!-- no translation found for quickcontact_missing_app (4600366393134289038) -->
<skip />
- <!-- no translation found for sms_disambig_title (4675399294513152364) -->
+ <!-- no translation found for quickcontact_remember_choice (5964536411579749424) -->
<skip />
- <!-- no translation found for make_primary (5829291915305113983) -->
+ <!-- no translation found for quickcontact_missing_name (5590266114306996632) -->
<skip />
- <string name="quickcontact_missing_app" msgid="1181287640680679441">"No se encontró aplicación para permitir esta acción"</string>
- <string name="quickcontact_remember_choice" msgid="2858356075887897116">"Recuerda esta opción"</string>
- <string name="quickcontact_missing_name" msgid="7806083820928955853">"Desconocido"</string>
<string name="menu_accounts" msgid="8499114602017077970">"Cuentas"</string>
- <!-- no translation found for menu_import_export (3765725645491577190) -->
- <skip />
- <!-- no translation found for dialog_import_export (4771877268244096596) -->
- <skip />
- <!-- no translation found for menu_share (943789700636542260) -->
- <skip />
- <!-- no translation found for share_via (563121028023030093) -->
- <skip />
- <!-- no translation found for share_error (4374508848981697170) -->
- <skip />
+ <string name="menu_import_export" msgid="3765725645491577190">"Importar/Exportar"</string>
+ <string name="dialog_import_export" msgid="4771877268244096596">"Importar/Exportar contactos"</string>
+ <string name="menu_share" msgid="943789700636542260">"Compartir"</string>
+ <string name="share_via" msgid="563121028023030093">"Compartir un contacto a través de"</string>
+ <string name="share_error" msgid="4374508848981697170">"Este contacto no se puede compartir."</string>
<string name="nameLabelsGroup" msgid="2034640839640477827">"Nombre"</string>
<string name="nicknameLabelsGroup" msgid="2891682101053358010">"Apodo"</string>
<string name="organizationLabelsGroup" msgid="2478611760751832035">"Organización"</string>
<string name="websiteLabelsGroup" msgid="4202998982804009261">"Sitio web"</string>
+ <!-- no translation found for eventLabelsGroup (8069912895912714412) -->
+ <skip />
<string name="type_short_home" msgid="7770424864090605384">"H"</string>
<string name="type_short_mobile" msgid="1655473281466676216">"Lun."</string>
<string name="type_short_work" msgid="4925330752504537861">"Mié."</string>
<string name="type_short_pager" msgid="2613818970827594238">"P"</string>
<string name="type_short_other" msgid="5669407180177236769">"Oct."</string>
- <string name="edit_secondary_collapse" msgid="1855127176548440583">"Detalles secundarios"</string>
+ <string name="edit_read_only" msgid="8158629550655830981">"Este contacto es de sólo lectura"</string>
+ <!-- no translation found for edit_secondary_collapse (5371618426594477103) -->
+ <skip />
<string name="dialog_primary_name" msgid="5521591005692614833">"Nombre principal"</string>
<string name="dialog_new_contact_account" msgid="9044704073286262197">"Crear contacto según la cuenta"</string>
<string name="menu_sync_remove" msgid="3266725887008450161">"Eliminar grupo de sincronización"</string>
- <!-- no translation found for dialog_sync_add (8267045393119375803) -->
+ <string name="dialog_sync_add" msgid="8267045393119375803">"Agregar grupo de sincronización"</string>
+ <string name="display_more_groups" msgid="2682547080423434170">"Más grupos…"</string>
+ <!-- no translation found for display_ungrouped (4602580795576261158) -->
<skip />
- <!-- no translation found for display_more_groups (2682547080423434170) -->
+ <!-- no translation found for display_all_contacts (6846131371214707956) -->
<skip />
- <string name="display_ungrouped" msgid="4357317661311803984">"(Contactos no agrupados)"</string>
<string name="display_warn_remove_ungrouped" msgid="2314043155909167610">"Al suprimir \"<xliff:g id="GROUP">%s</xliff:g>\" de sincronización también se suprimirá cualquier contacto no agrupado de la sincronización."</string>
<string name="account_phone" msgid="4025734638492419713">"Sólo telefónicamente (no sincronizado)"</string>
<string name="label_email_display_name" msgid="5537802602754309600">"Mostrar el nombre"</string>
+ <string name="call_custom" msgid="7756571794763171802">"Llamar a <xliff:g id="CUSTOM">%s</xliff:g>"</string>
<string name="call_home" msgid="1990519474420545392">"Llamar al hogar"</string>
<string name="call_mobile" msgid="7502236805487609178">"Llamar al celular"</string>
<string name="call_work" msgid="5328785911463744028">"Llamar al trabajo"</string>
<string name="call_fax_work" msgid="7467763592359059243">"Llamar al fax del trabajo"</string>
<string name="call_fax_home" msgid="8342175628887571876">"Llamar al fax personal"</string>
<string name="call_pager" msgid="9003902812293983281">"Llamar a localizador"</string>
- <string name="call_custom" msgid="7756571794763171802">"Llamar a <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="call_other" msgid="5605584621798108205">"Llamar a otro"</string>
+ <string name="call_callback" msgid="1910165691349426858">"Llamar a devolución de llamada"</string>
<string name="call_car" msgid="3280537320306436445">"Llamar al auto"</string>
<string name="call_company_main" msgid="6105120947138711257">"Llamar empresa principal"</string>
- <string name="call_mms" msgid="6274041545876221437">"Llamar a MMS"</string>
+ <string name="call_isdn" msgid="1541590690193403411">"Llamar a ISDN"</string>
+ <string name="call_main" msgid="6082900571803441339">"Llamada principal"</string>
+ <string name="call_other_fax" msgid="7777261153532968503">"Llamar a otro fax"</string>
<string name="call_radio" msgid="8296755876398357063">"Llamar a la radio"</string>
+ <string name="call_telex" msgid="2223170774548648114">"Llamar a télex"</string>
+ <string name="call_tty_tdd" msgid="8951266948204379604">"Llamar a TTY/TDD"</string>
+ <string name="call_work_mobile" msgid="8707874281430105394">"Llamar al celular del trabajo"</string>
+ <string name="call_work_pager" msgid="3419348514157949008">"Llamar al localizador del trabajo"</string>
+ <string name="call_assistant" msgid="2141641383068514308">"Llamar a <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="call_mms" msgid="6274041545876221437">"Llamar a MMS"</string>
+ <string name="sms_custom" msgid="5932736853732191825">"Texto <xliff:g id="CUSTOM">%s</xliff:g>"</string>
<string name="sms_home" msgid="7524332261493162995">"Enviar texto al hogar"</string>
<string name="sms_mobile" msgid="5200107250451030769">"Enviar texto a celular"</string>
<string name="sms_work" msgid="2269624156655267740">"Enviar texto al trabajo"</string>
@@ -334,11 +363,19 @@
<string name="sms_fax_home" msgid="9204042076306809634">"Enviar texto a fax personal"</string>
<string name="sms_pager" msgid="7730404569637015192">"Enviar texto a localizador"</string>
<string name="sms_other" msgid="5131921487474531617">"Enviar texto a otro"</string>
- <string name="sms_custom" msgid="5932736853732191825">"Texto <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="sms_callback" msgid="5004824430094288752">"Enviar texto a devolución de llamada"</string>
<string name="sms_car" msgid="7444227058437359641">"Enviar texto a auto"</string>
<string name="sms_company_main" msgid="118970873419678087">"Enviar texto a empresa principal"</string>
- <string name="sms_mms" msgid="4069352461380762677">"Enviar texto MMS"</string>
+ <string name="sms_isdn" msgid="8153785037515047845">"ISDN de texto"</string>
+ <string name="sms_main" msgid="8621625784504541679">"Texto principal"</string>
+ <string name="sms_other_fax" msgid="3930666870074006114">"Enviar texto a otro fax"</string>
<string name="sms_radio" msgid="3329166673433967820">"Enviar texto a radio"</string>
+ <string name="sms_telex" msgid="9034802430065267848">"Enviar texto a télex"</string>
+ <string name="sms_tty_tdd" msgid="6782284969132531532">"Enviar texto a TTY/TDD"</string>
+ <string name="sms_work_mobile" msgid="2459939960512702560">"Enviar texto al celular del trabajo"</string>
+ <string name="sms_work_pager" msgid="5566924423316960597">"Enviar texto a localizador del trabajo"</string>
+ <string name="sms_assistant" msgid="2773424339923116234">"Enviar texto a <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="sms_mms" msgid="4069352461380762677">"Enviar texto MMS"</string>
<string name="email_home" msgid="8573740658148184279">"Correo electrónico personal"</string>
<string name="email_mobile" msgid="2042889209787989814">"Correo electrónico celular"</string>
<string name="email_work" msgid="2807430017302722689">"Correo electrónico laboral"</string>
@@ -357,6 +394,7 @@
<string name="chat_gtalk" msgid="981575737258117697">"Chat mediante Google Talk"</string>
<string name="chat_icq" msgid="8438405386153745775">"Chat mediante ICQ"</string>
<string name="chat_jabber" msgid="7561444230307829609">"Chat mediante Jabber"</string>
+ <string name="chat" msgid="9025361898797412245">"Chat"</string>
<string name="postal_street" msgid="8133143961580058972">"Dirección postal"</string>
<string name="postal_pobox" msgid="4431938829180269821">"Apartado postal"</string>
<string name="postal_neighborhood" msgid="1450783874558956739">"Barrio"</string>
@@ -372,4 +410,8 @@
<string name="name_phonetic_given" msgid="6853570431394449191">"Nombre de pila fonético"</string>
<string name="name_phonetic_middle" msgid="8643721493320405200">"Segundo nombre fonético"</string>
<string name="name_phonetic_family" msgid="462095502140180305">"Nombre familiar fonético"</string>
+ <string name="split_label" msgid="8262112659919449087">"Dividir"</string>
+ <string name="split_explanation" msgid="1824739956426973592">"Transformar a estos datos en el contacto propio."</string>
+ <!-- no translation found for account_name_format (4421123930035299208) -->
+ <skip />
</resources>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 92b0eac..72ab82f 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -49,6 +49,7 @@
<!-- For ExportVCard -->
<item type="id" name="dialog_export_confirmation" />
+ <item type="id" name="dialog_exporting_vcard" />
<item type="id" name="dialog_fail_to_export_with_reason" />
</resources>
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 5e1638f..a0dcd6f 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -875,45 +875,44 @@
return AccountSelectionUtil.getSelectAccountDialog(this, id);
}
case R.id.dialog_sdcard_not_found: {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(this)
.setTitle(R.string.no_sdcard_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.no_sdcard_message)
- .setPositiveButton(android.R.string.ok, null);
- break;
+ .setPositiveButton(android.R.string.ok, null).create();
}
- case R.id.dialog_delete_contact_confirmation: {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ case R.id.dialog_delete_contact_confirmation: {
+ return new AlertDialog.Builder(this)
.setTitle(R.string.deleteConfirmation_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.deleteConfirmation)
.setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok, new DeleteClickListener(mSelectedContactUri));
- break;
+ .setPositiveButton(android.R.string.ok,
+ new DeleteClickListener(mSelectedContactUri)).create();
}
case R.id.dialog_cannot_delete_readonly_contact: {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(this)
.setTitle(R.string.deleteConfirmation_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.readOnlyContactWarning)
- .setPositiveButton(android.R.string.ok, null);
- break;
+ .setPositiveButton(android.R.string.ok, null).create();
}
case R.id.dialog_readonly_contact_delete_confirmation: {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ return new AlertDialog.Builder(this)
.setTitle(R.string.deleteConfirmation_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.readOnlyContactDeleteConfirmation)
- .setPositiveButton(android.R.string.ok, new DeleteClickListener(mSelectedContactUri));
- }
- case R.id.dialog_multiple_contact_delete_confirmation: {
- AlertDialog.Builder builder = new AlertDialog.Builder(this)
+ .setPositiveButton(android.R.string.ok,
+ new DeleteClickListener(mSelectedContactUri)).create();
+ }
+ case R.id.dialog_multiple_contact_delete_confirmation: {
+ return new AlertDialog.Builder(this)
.setTitle(R.string.deleteConfirmation_title)
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.multipleContactDeleteConfirmation)
- .setPositiveButton(android.R.string.ok, new DeleteClickListener(mSelectedContactUri));
- }
-
+ .setPositiveButton(android.R.string.ok,
+ new DeleteClickListener(mSelectedContactUri)).create();
+ }
}
return super.onCreateDialog(id);
}
@@ -1988,7 +1987,8 @@
}
final static class ContactListItemCache {
- public TextView header;
+ public View header;
+ public TextView headerText;
public View divider;
public TextView nameView;
public View callView;
@@ -2292,7 +2292,8 @@
final View view = super.newView(context, cursor, parent);
final ContactListItemCache cache = new ContactListItemCache();
- cache.header = (TextView) view.findViewById(R.id.header);
+ cache.header = view.findViewById(R.id.header);
+ cache.headerText = (TextView)view.findViewById(R.id.header_text);
cache.divider = view.findViewById(R.id.list_divider);
cache.nameView = (TextView) view.findViewById(R.id.name);
cache.callView = view.findViewById(R.id.call_view);
@@ -2491,8 +2492,13 @@
} else {
final int section = getSectionForPosition(position);
if (getPositionForSection(section) == position) {
- cache.header.setText(mIndexer.getSections()[section].toString());
- cache.header.setVisibility(View.VISIBLE);
+ String title = mIndexer.getSections()[section].toString().trim();
+ if (!TextUtils.isEmpty(title)) {
+ cache.headerText.setText(title);
+ cache.header.setVisibility(View.VISIBLE);
+ } else {
+ cache.header.setVisibility(View.GONE);
+ }
} else {
cache.header.setVisibility(View.GONE);
}
diff --git a/src/com/android/contacts/ExportVCardActivity.java b/src/com/android/contacts/ExportVCardActivity.java
index 7c088ea..baf2371 100644
--- a/src/com/android/contacts/ExportVCardActivity.java
+++ b/src/com/android/contacts/ExportVCardActivity.java
@@ -51,6 +51,7 @@
private Set<String> mExtensionsToConsider;
private ProgressDialog mProgressDialog;
+ private String mExportingFileName;
private Handler mHandler = new Handler();
@@ -101,15 +102,8 @@
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
mActualExportThread = new ActualExportThread(mFileName);
- String title = getString(R.string.exporting_contact_list_title);
- String message = getString(R.string.exporting_contact_list_message, mFileName);
- mProgressDialog = new ProgressDialog(ExportVCardActivity.this);
- mProgressDialog.setTitle(title);
- mProgressDialog.setMessage(message);
- mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- mProgressDialog.setOnCancelListener(mActualExportThread);
- mProgressDialog.show();
mActualExportThread.start();
+ showDialog(R.id.dialog_exporting_vcard);
}
}
}
@@ -117,11 +111,10 @@
private class ActualExportThread extends Thread
implements DialogInterface.OnCancelListener {
private PowerManager.WakeLock mWakeLock;
- private String mFileName;
private boolean mCanceled = false;
public ActualExportThread(String fileName) {
- mFileName = fileName;
+ mExportingFileName = fileName;
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(
PowerManager.SCREEN_DIM_WAKE_LOCK |
@@ -136,11 +129,11 @@
try {
OutputStream outputStream = null;
try {
- outputStream = new FileOutputStream(mFileName);
+ outputStream = new FileOutputStream(mExportingFileName);
} catch (FileNotFoundException e) {
final String errorReason =
getString(R.string.fail_reason_could_not_open_file,
- mFileName, e.getMessage());
+ mExportingFileName, e.getMessage());
shouldCallFinish = false;
mHandler.post(new ErrorReasonDisplayer(errorReason));
return;
@@ -291,11 +284,29 @@
.setIcon(android.R.drawable.ic_dialog_alert)
.setMessage(R.string.no_sdcard_message)
.setPositiveButton(android.R.string.ok, mCancelListener);
+ return builder.create();
+ }
+ case R.id.dialog_exporting_vcard: {
+ return getExportingVCardDialog();
}
}
return super.onCreateDialog(id);
}
+ private Dialog getExportingVCardDialog() {
+ if (mProgressDialog == null) {
+ String title = getString(R.string.exporting_contact_list_title);
+ String message = getString(R.string.exporting_contact_list_message,
+ mExportingFileName);
+ mProgressDialog = new ProgressDialog(ExportVCardActivity.this);
+ mProgressDialog.setTitle(title);
+ mProgressDialog.setMessage(message);
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ mProgressDialog.setOnCancelListener(mActualExportThread);
+ }
+ return mProgressDialog;
+ }
+
@Override
protected void onPrepareDialog(int id, Dialog dialog) {
if (id == R.id.dialog_fail_to_export_with_reason) {
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index 6e993ba..ab8e931 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -17,8 +17,6 @@
package com.android.contacts;
import com.android.contacts.Collapser.Collapsible;
-import com.android.contacts.ScrollingTabWidget.OnTabSelectionChangedListener;
-import com.android.contacts.SplitAggregateView.OnContactSelectedListener;
import com.android.contacts.model.ContactsSource;
import com.android.contacts.model.Sources;
import com.android.contacts.model.ContactsSource.DataKind;
@@ -40,7 +38,6 @@
import android.content.Entity;
import android.content.EntityIterator;
import android.content.Intent;
-import android.content.DialogInterface.OnClickListener;
import android.content.Entity.NamedContentValues;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -62,9 +59,7 @@
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
import android.view.ContextMenu;
-import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -74,9 +69,6 @@
import android.view.ViewGroup;
import android.view.Window;
import android.view.ContextMenu.ContextMenuInfo;
-import android.view.animation.Animation;
-import android.view.animation.TranslateAnimation;
-import android.view.animation.Animation.AnimationListener;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -551,7 +543,7 @@
} else if (requestCode == REQUEST_EDIT_CONTACT) {
if (resultCode == EditContactActivity.RESULT_CLOSE_VIEW_ACTIVITY) {
finish();
- } else {
+ } else if (resultCode == Activity.RESULT_OK) {
mLookupUri = intent.getData();
if (mLookupUri == null) {
finish();
diff --git a/src/com/android/contacts/model/ContactsSource.java b/src/com/android/contacts/model/ContactsSource.java
index f0c21e3..f82f8a1 100644
--- a/src/com/android/contacts/model/ContactsSource.java
+++ b/src/com/android/contacts/model/ContactsSource.java
@@ -138,6 +138,10 @@
}
}
+ abstract public int getHeaderColor(Context context);
+
+ abstract public int getSideBarColor(Context context);
+
/**
* {@link Comparator} to sort by {@link DataKind#weight}.
*/
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/EntityDelta.java
index dfc4fc4..2581480 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/EntityDelta.java
@@ -106,7 +106,7 @@
if (local == null) local = new EntityDelta();
if (LOGV) {
- final Long localVersion = (local.mValues == null) ? -1 : local.mValues
+ final Long localVersion = (local.mValues == null) ? null : local.mValues
.getAsLong(RawContacts.VERSION);
final Long remoteVersion = remote.mValues.getAsLong(RawContacts.VERSION);
Log.d(TAG, "Re-parenting from original version " + remoteVersion + " to "
diff --git a/src/com/android/contacts/model/ExchangeSource.java b/src/com/android/contacts/model/ExchangeSource.java
index 6d4e357..5161499 100644
--- a/src/com/android/contacts/model/ExchangeSource.java
+++ b/src/com/android/contacts/model/ExchangeSource.java
@@ -272,4 +272,14 @@
return kind;
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff876b47;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffc6ab8c;
+ }
}
diff --git a/src/com/android/contacts/model/ExternalSource.java b/src/com/android/contacts/model/ExternalSource.java
index f22aba4..11e06c3 100644
--- a/src/com/android/contacts/model/ExternalSource.java
+++ b/src/com/android/contacts/model/ExternalSource.java
@@ -77,7 +77,7 @@
* <p>
* In the future this may be inflated from XML defined by a data source.
*/
-public class ExternalSource extends ContactsSource {
+public class ExternalSource extends FallbackSource {
private static final String ACTION_SYNC_ADAPTER = "android.content.SyncAdapter";
private static final String METADATA_CONTACTS = "android.provider.CONTACTS_STRUCTURE";
@@ -109,6 +109,12 @@
if (parser == null) continue;
inflate(context, parser);
}
+
+ // Bring in name and photo from fallback source, which are non-optional
+ inflateStructuredName(inflateLevel);
+ inflatePhoto(inflateLevel);
+
+ setInflatedLevel(inflateLevel);
}
/**
@@ -258,4 +264,14 @@
return mPublishedMode ? inflatePublished(status.published) : status.title;
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff7f93bc;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffbdc7d8;
+ }
}
diff --git a/src/com/android/contacts/model/FallbackSource.java b/src/com/android/contacts/model/FallbackSource.java
index ebef42b..ca405eb 100644
--- a/src/com/android/contacts/model/FallbackSource.java
+++ b/src/com/android/contacts/model/FallbackSource.java
@@ -621,4 +621,14 @@
}
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff7f93bc;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffbdc7b8;
+ }
}
diff --git a/src/com/android/contacts/model/GoogleSource.java b/src/com/android/contacts/model/GoogleSource.java
index 010982c..e8f7f46 100644
--- a/src/com/android/contacts/model/GoogleSource.java
+++ b/src/com/android/contacts/model/GoogleSource.java
@@ -260,4 +260,14 @@
cursor.close();
}
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0xff000000;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffffffff;
+ }
}
diff --git a/src/com/android/contacts/ui/EditContactActivity.java b/src/com/android/contacts/ui/EditContactActivity.java
index 7c644f0..36c1551 100644
--- a/src/com/android/contacts/ui/EditContactActivity.java
+++ b/src/com/android/contacts/ui/EditContactActivity.java
@@ -16,6 +16,26 @@
package com.android.contacts.ui;
+import com.android.contacts.ContactsListActivity;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.ScrollingTabWidget;
+import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Editor;
+import com.android.contacts.model.EntityDelta;
+import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.EntitySet;
+import com.android.contacts.model.GoogleSource;
+import com.android.contacts.model.Sources;
+import com.android.contacts.model.Editor.EditorListener;
+import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.ui.widget.ContactEditorView;
+import com.android.contacts.ui.widget.PhotoEditorView;
+import com.android.contacts.util.EmptyService;
+import com.android.contacts.util.WeakAsyncTask;
+import com.android.internal.widget.ContactHeaderWidget;
+import com.google.android.collect.Lists;
+
import android.accounts.Account;
import android.app.Activity;
import android.app.AlertDialog;
@@ -35,7 +55,6 @@
import android.content.ContentProviderOperation.Builder;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
@@ -45,12 +64,9 @@
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts.Data;
-import android.text.TextUtils;
import android.util.Log;
-import android.util.SparseArray;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -59,38 +75,19 @@
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
+import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.TextView;
import android.widget.Toast;
-import com.android.contacts.ContactsListActivity;
-import com.android.contacts.ContactsUtils;
-import com.android.contacts.R;
-import com.android.contacts.ScrollingTabWidget;
-import com.android.contacts.model.ContactsSource;
-import com.android.contacts.model.Editor;
-import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.EntityModifier;
-import com.android.contacts.model.EntitySet;
-import com.android.contacts.model.GoogleSource;
-import com.android.contacts.model.Sources;
-import com.android.contacts.model.Editor.EditorListener;
-import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.ui.widget.ContactEditorView;
-import com.android.contacts.util.EmptyService;
-import com.android.contacts.util.WeakAsyncTask;
-import com.android.internal.widget.ContactHeaderWidget;
-import com.google.android.collect.Lists;
-
import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
* Activity for editing or inserting a contact.
*/
-public final class EditContactActivity extends Activity implements View.OnClickListener,
- ScrollingTabWidget.OnTabSelectionChangedListener,
- ContactHeaderWidget.ContactHeaderListener, EditorListener {
+public final class EditContactActivity extends Activity
+ implements View.OnClickListener {
private static final String TAG = "EditContactActivity";
/** The launch code when picking a photo and the raw data is returned */
@@ -100,7 +97,7 @@
private static final int REQUEST_JOIN_CONTACT = 3022;
private static final String KEY_EDIT_STATE = "state";
- private static final String KEY_SELECTED_RAW_CONTACT = "selected";
+ private static final String KEY_RAW_CONTACT_ID_REQUESTING_PHOTO = "photorequester";
/** The result code when view activity should close after edit returns */
public static final int RESULT_CLOSE_VIEW_ACTIVITY = 777;
@@ -109,17 +106,16 @@
public static final int SAVE_MODE_SPLIT = 1;
public static final int SAVE_MODE_JOIN = 2;
+ private long mRawContactIdRequestingPhoto = -1;
- private String mQuerySelection;
- private ScrollingTabWidget mTabWidget;
- private ContactHeaderWidget mHeader;
- private TextView mAccountName;
+ String mQuerySelection;
- private ContactEditorView mEditor;
-
- private EntitySet mState;
private long mContactIdForJoin;
+ EntitySet mState;
+
+ /** The linear layout holding the ContactEditorViews */
+ LinearLayout mContent;
private ArrayList<Dialog> mManagedDialogs = Lists.newArrayList();
@@ -127,29 +123,13 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
- final Context context = this;
- final LayoutInflater inflater = this.getLayoutInflater();
-
final Intent intent = getIntent();
final String action = intent.getAction();
- final Bundle extras = intent.getExtras();
setContentView(R.layout.act_edit);
- // Header bar is filled later after queries finish
- mHeader = (ContactHeaderWidget)this.findViewById(R.id.contact_header_widget);
- mHeader.setContactHeaderListener(this);
- mHeader.showStar(false);
- mHeader.enableClickListeners();
-
- mTabWidget = (ScrollingTabWidget)this.findViewById(R.id.tab_widget);
- mTabWidget.setTabSelectionListener(this);
- mAccountName = (TextView)mTabWidget.findViewById(R.id.account_name);
-
// Build editor and listen for photo requests
- mEditor = (ContactEditorView)this.findViewById(android.R.id.tabcontent);
- mEditor.getPhotoEditor().setEditorListener(this);
- mEditor.setNameEditorListener(this);
+ mContent = (LinearLayout) findViewById(R.id.editors);
findViewById(R.id.btn_done).setOnClickListener(this);
findViewById(R.id.btn_discard).setOnClickListener(this);
@@ -160,12 +140,9 @@
if (Intent.ACTION_EDIT.equals(action) && !hasIncomingState) {
// Read initial state from database
new QueryEntitiesTask(this).execute(intent);
- mHeader.showStar(true);
- mHeader.setContactUri(intent.getData(), false);
} else if (Intent.ACTION_INSERT.equals(action) && !hasIncomingState) {
// Trigger dialog to pick account type
doAddAction();
- mHeader.showStar(false);
}
}
@@ -227,8 +204,7 @@
@Override
protected void onPostExecute(EditContactActivity target, Void result) {
// Bind UI to new background state
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
@@ -239,9 +215,9 @@
if (hasValidState()) {
// Store entities with modifications
outState.putParcelable(KEY_EDIT_STATE, mState);
- outState.putLong(KEY_SELECTED_RAW_CONTACT, getSelectedRawContactId());
}
+ outState.putLong(KEY_RAW_CONTACT_ID_REQUESTING_PHOTO, mRawContactIdRequestingPhoto);
super.onSaveInstanceState(outState);
}
@@ -249,16 +225,10 @@
protected void onRestoreInstanceState(Bundle savedInstanceState) {
// Read modifications from instance
mState = savedInstanceState.<EntitySet> getParcelable(KEY_EDIT_STATE);
+ mRawContactIdRequestingPhoto = savedInstanceState.getLong(
+ KEY_RAW_CONTACT_ID_REQUESTING_PHOTO);
+ bindEditors();
- bindTabs();
- bindHeader();
-
- if (hasValidState()) {
- final Long selectedId = savedInstanceState.getLong(KEY_SELECTED_RAW_CONTACT);
- setSelectedRawContactId(selectedId);
- }
-
- // Restore selected tab and any focus
super.onRestoreInstanceState(savedInstanceState);
}
@@ -285,47 +255,12 @@
/**
* Show this {@link Dialog} and manage with the {@link Activity}.
*/
- private void showAndManageDialog(Dialog dialog) {
+ void showAndManageDialog(Dialog dialog) {
startManagingDialog(dialog);
dialog.show();
}
/**
- * Return the {@link RawContacts#_ID} of the currently selected tab.
- */
- protected Long getSelectedRawContactId() {
- final int tabIndex = mTabWidget.getCurrentTab();
- return this.mTabRawContacts.get(tabIndex);
- }
-
- /**
- * Return the {@link EntityDelta} for the currently selected tab.
- */
- protected EntityDelta getSelectedEntityDelta() {
- final Long rawContactId = getSelectedRawContactId();
- return mState.getByRawContactId(rawContactId);
- }
-
- /**
- * Set the selected tab based on the given {@link RawContacts#_ID}.
- */
- protected void setSelectedRawContactId(Long rawContactId) {
- int tabIndex = 0;
-
- // Find index of requested contact
- final int size = mTabRawContacts.size();
- for (int i = 0; i < size; i++) {
- if (mTabRawContacts.valueAt(i) == rawContactId) {
- tabIndex = i;
- break;
- }
- }
-
- mTabWidget.setCurrentTab(tabIndex);
- this.onTabSelectionChanged(tabIndex, false);
- }
-
- /**
* Check if our internal {@link #mState} is valid, usually checked before
* performing user actions.
*/
@@ -333,131 +268,55 @@
return mState != null && mState.size() > 0;
}
-
-
/**
- * Map from {@link #mTabWidget} indexes to {@link RawContacts#_ID}, usually
- * used when mapping to {@link #mState}.
- */
- private SparseArray<Long> mTabRawContacts = new SparseArray<Long>();
-
-
- /**
- * Rebuild tabs to match our underlying {@link #mState} object, usually
+ * Rebuild the editors to match our underlying {@link #mState} object, usually
* called once we've parsed {@link Entity} data or have inserted a new
* {@link RawContacts}.
*/
- protected void bindTabs() {
+ protected void bindEditors() {
if (!hasValidState()) return;
+ final LayoutInflater inflater = (LayoutInflater) getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
final Sources sources = Sources.getInstance(this);
- final Long selectedRawContactId = this.getSelectedRawContactId();
- // Remove any existing tabs and rebuild any visible
- mTabWidget.removeAllTabs();
- mTabRawContacts.clear();
- for (EntityDelta entity : mState) {
+ // Remove any existing editors and rebuild any visible
+
+ mContent.removeAllViews();
+ int size = mState.size();
+ for (int i = 0; i < size; i++) {
+ // TODO ensure proper ordering of entities in the list
+ EntityDelta entity = mState.get(i);
final ValuesDelta values = entity.getValues();
if (!values.isVisible()) continue;
final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
- final Long rawContactId = values.getAsLong(RawContacts._ID);
final ContactsSource source = sources.getInflatedSource(accountType,
ContactsSource.LEVEL_CONSTRAINTS);
+ final long rawContactId = values.getAsLong(RawContacts._ID);
- final int tabIndex = mTabWidget.getTabCount();
- final View tabView = ContactsUtils.createTabIndicatorView(
- mTabWidget.getTabParent(), source);
- mTabWidget.addTab(tabView);
- mTabRawContacts.put(tabIndex, rawContactId);
- }
+ ContactEditorView editor = (ContactEditorView) inflater.inflate(
+ R.layout.item_contact_editor, mContent, false);
+ editor.getPhotoEditor().setEditorListener(new EditorListener() {
- final boolean hasActiveTabs = mTabWidget.getTabCount() > 0;
- if (hasActiveTabs) {
- // Focus on last selected contact
- this.setSelectedRawContactId(selectedRawContactId);
- } else {
- // Nothing remains to edit, save and bail entirely
- this.doSaveAction(SAVE_MODE_DEFAULT);
+ public void onDeleted(Editor editor) {
+ }
+
+ public void onRequest(int request) {
+ if (!hasValidState()) return;
+
+ if (request == EditorListener.REQUEST_PICK_PHOTO) {
+ doPickPhotoAction(rawContactId);
+ }
+ }
+ });
+
+ mContent.addView(editor);
+ editor.setState(entity, source);
}
// Show editor now that we've loaded state
- mEditor.setVisibility(View.VISIBLE);
- }
-
- /**
- * Bind our header based on {@link #mState}, which include any edits.
- * Usually called once {@link Entity} data has been loaded, or after a
- * primary {@link Data} change.
- */
- protected void bindHeader() {
- if (!hasValidState()) return;
-
- boolean starred = false;
-
- ValuesDelta photoDelta = mState.getSuperPrimaryEntry(Photo.CONTENT_ITEM_TYPE);
- if (photoDelta != null) {
- final byte[] photoBytes = photoDelta.getAsByteArray(Photo.PHOTO);
- if (photoBytes != null) {
- Bitmap photo = BitmapFactory.decodeByteArray(photoBytes, 0,
- photoBytes.length);
- mHeader.setPhoto(photo);
- }
- }
-
- ValuesDelta nameDelta = mState.getSuperPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
- if (nameDelta != null) {
- String visibleName = getVisibleName(nameDelta);
- if (visibleName != null) {
- mHeader.setDisplayName(visibleName, null);
- }
- }
-
- for (EntityDelta delta : mState) {
- Long isCurrStarred = delta.getValues().getAsLong(RawContacts.STARRED);
- starred = starred || (isCurrStarred != null && isCurrStarred != 0);
- }
- mHeader.setStared(starred);
- }
-
- private static String getVisibleName(ValuesDelta nameDelta) {
- final String givenName = nameDelta.getAsString(StructuredName.GIVEN_NAME);
- final String familyName = nameDelta.getAsString(StructuredName.FAMILY_NAME);
- final boolean hasGiven = !TextUtils.isEmpty(givenName);
- final boolean hasFamily = !TextUtils.isEmpty(familyName);
-
- if (hasGiven && hasFamily) {
- return givenName + " " + familyName;
- } else if (hasFamily) {
- return familyName;
- } else if (hasGiven) {
- return givenName;
- } else {
- return null;
- }
- }
-
- /** {@inheritDoc} */
- public void onTabSelectionChanged(int tabIndex, boolean clicked) {
- if (!hasValidState()) return;
-
- // Find entity and source for selected tab
- final EntityDelta entity = this.getSelectedEntityDelta();
- if (entity == null) return;
-
- final Sources sources = Sources.getInstance(this);
- final ValuesDelta values = entity.getValues();
- final String accountType = values.getAsString(RawContacts.ACCOUNT_TYPE);
- final String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
- final ContactsSource source = sources.getInflatedSource(accountType,
- ContactsSource.LEVEL_CONSTRAINTS);
-
- mAccountName.setText(getString(R.string.account_name_format,
- source.getDisplayLabel(this), accountName));
- mAccountName.setVisibility(View.VISIBLE);
-
- // Assign editor state based on entity and source
- mEditor.setState(entity, source);
+ mContent.setVisibility(View.VISIBLE);
}
/** {@inheritDoc} */
@@ -498,11 +357,29 @@
switch (requestCode) {
case PHOTO_PICKED_WITH_DATA: {
- // When reaching this point, we've already inflated our tab
- // state and returned to the last-visible tab.
- final Bitmap photo = data.getParcelableExtra("data");
- mEditor.setPhotoBitmap(photo);
- bindHeader();
+ ContactEditorView requestingEditor = null;
+ if (mRawContactIdRequestingPhoto > 0) {
+ for (int i = 0; i < mContent.getChildCount(); i++) {
+ View childView = mContent.getChildAt(i);
+ if (childView instanceof ContactEditorView) {
+ ContactEditorView editor = (ContactEditorView) childView;
+ if (editor.getRawContactId() == mRawContactIdRequestingPhoto) {
+ requestingEditor = editor;
+ break;
+ }
+ }
+ }
+ }
+
+ if (requestingEditor != null) {
+ final Bitmap photo = data.getParcelableExtra("data");
+ requestingEditor.setPhotoBitmap(photo);
+ mRawContactIdRequestingPhoto = -1;
+ } else {
+ // The contact that requested the photo is no longer present.
+ // TODO: Show error message
+ }
+
break;
}
@@ -525,17 +402,6 @@
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- final boolean hasPhotoEditor = mEditor.hasPhotoEditor();
- final boolean hasSetPhoto = mEditor.hasSetPhoto();
-
- menu.findItem(R.id.menu_photo_add).setVisible(hasPhotoEditor);
- menu.findItem(R.id.menu_photo_remove).setVisible(hasSetPhoto);
-
- return true;
- }
-
- @Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_done:
@@ -546,10 +412,6 @@
return doAddAction();
case R.id.menu_delete:
return doDeleteAction();
- case R.id.menu_photo_add:
- return doPickPhotoAction();
- case R.id.menu_photo_remove:
- return doRemovePhotoAction();
case R.id.menu_split:
return doSplitContactAction();
case R.id.menu_join:
@@ -637,7 +499,7 @@
} catch (OperationApplicationException e) {
// Version consistency failed, re-parent change and try again
- Log.w(TAG, "Version consistency failed, re-parenting", e);
+ Log.w(TAG, "Version consistency failed, re-parenting: " + e.toString());
final EntitySet newState = EntitySet.fromQuery(resolver,
target.mQuerySelection, null, null);
state = EntitySet.mergeAfter(newState, state);
@@ -692,7 +554,7 @@
* Saves or creates the contact based on the mode, and if successful
* finishes the activity.
*/
- private boolean doSaveAction(int saveMode) {
+ boolean doSaveAction(int saveMode) {
if (!hasValidState()) return false;
final PersistTask task = new PersistTask(this, saveMode);
@@ -845,51 +707,25 @@
/**
* Pick a specific photo to be added under the currently selected tab.
*/
- private boolean doPickPhotoAction() {
+ private boolean doPickPhotoAction(long rawContactId) {
if (!hasValidState()) return false;
try {
// Launch picker to choose photo for selected contact
final Intent intent = ContactsUtils.getPhotoPickIntent();
startActivityForResult(intent, PHOTO_PICKED_WITH_DATA);
+ mRawContactIdRequestingPhoto = rawContactId;
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.photoPickerNotFoundText, Toast.LENGTH_LONG).show();
}
return true;
}
- /**
- * Clear any existing photo under the currently selected tab.
- */
- public boolean doRemovePhotoAction() {
- if (!hasValidState()) return false;
-
- // Remove photo from selected contact
- mEditor.setPhotoBitmap(null);
- return true;
- }
-
/** {@inheritDoc} */
public void onDeleted(Editor editor) {
// Ignore any editor deletes
}
- /** {@inheritDoc} */
- public void onRequest(int request) {
- if (!hasValidState()) return;
-
- switch (request) {
- case EditorListener.REQUEST_PICK_PHOTO: {
- doPickPhotoAction();
- break;
- }
- case EditorListener.FIELD_CHANGED: {
- bindHeader();
- break;
- }
- }
- }
-
private boolean doSplitContactAction() {
mState.splitRawContacts();
return doSaveAction(SAVE_MODE_SPLIT);
@@ -976,8 +812,7 @@
// Update the UI.
EditContactActivity target = mTarget.get();
if (target != null) {
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
};
@@ -1061,8 +896,7 @@
// Account was auto-selected on the background thread,
// but we need to update the UI still in the
// now-current UI thread.
- target.bindTabs();
- target.bindHeader();
+ target.bindEditors();
}
}
}
@@ -1076,13 +910,14 @@
builder.setMessage(R.string.deleteConfirmation);
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- // Mark the currently selected contact for deletion
- final EntityDelta delta = getSelectedEntityDelta();
- if (delta == null) return;
- delta.markDeleted();
+ // Mark all raw contacts for deletion
+ for (EntityDelta delta : mState) {
+ delta.markDeleted();
+ }
- bindTabs();
- bindHeader();
+ // Save the deletes
+ doSaveAction(SAVE_MODE_DEFAULT);
+ finish();
}
});
builder.setNegativeButton(android.R.string.cancel, null);
@@ -1138,9 +973,6 @@
final ValuesDelta structuredName = allNames.get(which);
structuredName.put(Data.IS_PRIMARY, 1);
structuredName.put(Data.IS_SUPER_PRIMARY, 1);
-
- // Update header based on edited values
- bindHeader();
}
};
diff --git a/src/com/android/contacts/ui/QuickContactActivity.java b/src/com/android/contacts/ui/QuickContactActivity.java
index 5cd2d18..86dca28 100644
--- a/src/com/android/contacts/ui/QuickContactActivity.java
+++ b/src/com/android/contacts/ui/QuickContactActivity.java
@@ -22,6 +22,7 @@
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.QuickContact;
+import android.util.Log;
/**
* Stub translucent activity that just shows {@link QuickContactWindow} floating
@@ -30,18 +31,35 @@
*/
public final class QuickContactActivity extends Activity implements
QuickContactWindow.OnDismissListener {
+ private static final String TAG = "FastTrackActivity";
+
+ static final boolean LOGV = true;
+ static final boolean FORCE_CREATE = false;
+
private QuickContactWindow mQuickContact;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ this.onNewIntent(getIntent());
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ if (LOGV) Log.d(TAG, "onNewIntent");
if (QuickContactWindow.TRACE_LAUNCH) {
android.os.Debug.startMethodTracing(QuickContactWindow.TRACE_TAG);
}
+ if (mQuickContact == null || FORCE_CREATE) {
+ if (LOGV) Log.d(TAG, "Preparing window");
+ mQuickContact = new QuickContactWindow(this, this);
+ }
+
// Use our local window token for now
- final Intent intent = getIntent();
final Uri lookupUri = intent.getData();
final Bundle extras = intent.getExtras();
@@ -50,19 +68,44 @@
final int mode = extras.getInt(QuickContact.EXTRA_MODE, QuickContact.MODE_MEDIUM);
final String[] excludeMimes = extras.getStringArray(QuickContact.EXTRA_EXCLUDE_MIMES);
- mQuickContact = new QuickContactWindow(this, this);
mQuickContact.show(lookupUri, target, mode, excludeMimes);
}
+ /** {@inheritDoc} */
@Override
- protected void onStop() {
- super.onStop();
+ public void onBackPressed() {
+ if (LOGV) Log.w(TAG, "Unexpected back captured by stub activity");
+ finish();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (LOGV) Log.d(TAG, "onPause");
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (LOGV) Log.d(TAG, "onDestroy");
+
mQuickContact.dismiss();
}
/** {@inheritDoc} */
public void onDismiss(QuickContactWindow dialog) {
- // When dismissed, finish this activity
- finish();
+ if (LOGV) Log.d(TAG, "onDismiss");
+
+ if (isTaskRoot() && !FORCE_CREATE) {
+ if (LOGV) Log.d(TAG, "Moving task to back");
+
+ // Instead of stopping, simply push this to the back of the stack.
+ // This is only done when running at the top of the stack;
+ // otherwise, we have been launched by someone else so need to
+ // allow the user to go back to the caller.
+ moveTaskToBack(false);
+ } else {
+ finish();
+ }
}
}
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index 6059079..756dd1e 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -16,6 +16,7 @@
package com.android.contacts.ui;
+import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
import com.android.contacts.model.ContactsSource;
import com.android.contacts.model.Sources;
@@ -24,6 +25,8 @@
import com.android.contacts.util.Constants;
import com.android.contacts.util.NotifyingAsyncQueryHandler;
import com.android.internal.policy.PolicyManager;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
import android.content.ActivityNotFoundException;
import android.content.ContentValues;
@@ -31,23 +34,34 @@
import android.content.Context;
import android.content.EntityIterator;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Handler;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.QuickContact;
-import android.provider.ContactsContract.Presence;
import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StatusUpdates;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.SocialContract.Activities;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.Log;
+import android.util.Pool;
+import android.util.Poolable;
+import android.util.PoolableManager;
+import android.util.Pools;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
@@ -55,11 +69,13 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
+import android.view.Window.Callback;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -76,19 +92,20 @@
import android.widget.Toast;
import java.lang.ref.SoftReference;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
- * Window that shows fast-track contact details for a specific
- * {@link Contacts#_ID}.
+ * Window that shows QuickContact dialog for a specific {@link Contacts#_ID}.
*/
public class QuickContactWindow implements Window.Callback,
NotifyingAsyncQueryHandler.AsyncQueryListener, View.OnClickListener,
- AbsListView.OnItemClickListener, CompoundButton.OnCheckedChangeListener {
+ AbsListView.OnItemClickListener, CompoundButton.OnCheckedChangeListener, KeyEvent.Callback {
private static final String TAG = "QuickContactWindow";
/**
@@ -113,15 +130,13 @@
private OnDismissListener mDismissListener;
private ResolveCache mResolveCache;
- private long mAggId;
+ private Uri mLookupUri;
private Rect mAnchor;
private int mShadowHeight;
- private boolean mHasSummary = false;
- private boolean mHasSocial = false;
private boolean mHasValidSocial = false;
- private boolean mHasActions = false;
+ private boolean mHasData = false;
private boolean mMakePrimary = false;
private ImageView mArrowUp;
@@ -139,35 +154,59 @@
private CheckableImageView mLastAction;
private CheckBox mSetPrimaryCheckBox;
+ private int mWindowRecycled = 0;
+ private int mActionRecycled = 0;
+
/**
* Set of {@link Action} that are associated with the aggregate currently
- * displayed by this fast-track window, represented as a map from
- * {@link String} MIME-type to {@link ActionList}.
+ * displayed by this dialog, represented as a map from {@link String}
+ * MIME-type to {@link ActionList}.
*/
private ActionMap mActions = new ActionMap();
+ /**
+ * Pool of unused {@link CheckableImageView} that have previously been
+ * inflated, and are ready to be recycled through {@link #obtainView()}.
+ */
+ private LinkedList<View> mActionPool = new LinkedList<View>();
+
private String[] mExcludeMimes;
/**
- * Specific mime-types that should be bumped to the front of the fast-track.
- * Other mime-types not appearing in this list follow in alphabetic order.
+ * Specific MIME-types that should be bumped to the front of the dialog.
+ * Other MIME-types not appearing in this list follow in alphabetic order.
*/
private static final String[] ORDERED_MIMETYPES = new String[] {
- Phone.CONTENT_ITEM_TYPE,
- Contacts.CONTENT_ITEM_TYPE,
- Constants.MIME_SMS_ADDRESS,
- Email.CONTENT_ITEM_TYPE,
+ Phone.CONTENT_ITEM_TYPE,
+ Contacts.CONTENT_ITEM_TYPE,
+ Constants.MIME_SMS_ADDRESS,
+ Email.CONTENT_ITEM_TYPE,
};
- private static final int TOKEN_SUMMARY = 1;
- private static final int TOKEN_SOCIAL = 2;
- private static final int TOKEN_DATA = 3;
+ /**
+ * Specific list {@link ApplicationInfo#packageName} of apps that are
+ * prefered <strong>only</strong> for the purposes of default icons when
+ * multiple {@link ResolveInfo} are found to match. This only happens when
+ * the user has not selected a default app yet, and they will still be
+ * presented with the system disambiguation dialog.
+ */
+ private static final HashSet<String> sPreferResolve = Sets.newHashSet(new String[] {
+ "com.android.email",
+ "com.android.calendar",
+ "com.android.contacts",
+ "com.android.mms",
+ "com.android.phone",
+ });
+
+ private static final int TOKEN_DATA = 1;
+
+ static final boolean LOGD = false;
static final boolean TRACE_LAUNCH = false;
static final String TRACE_TAG = "quickcontact";
/**
- * Prepare a fast-track window to show in the given {@link Context}.
+ * Prepare a dialog to show in the given {@link Context}.
*/
public QuickContactWindow(Context context) {
mContext = new ContextThemeWrapper(context, R.style.QuickContact);
@@ -208,12 +247,13 @@
return 1.2f - inner * inner;
}
});
+
+ mHandler = new NotifyingAsyncQueryHandler(mContext, this);
}
/**
- * Prepare a fast-track window to show in the given {@link Context}, and
- * notify the given {@link OnDismissListener} each time this dialog is
- * dismissed.
+ * Prepare a dialog to show in the given {@link Context}, and notify the
+ * given {@link OnDismissListener} each time this dialog is dismissed.
*/
public QuickContactWindow(Context context, OnDismissListener dismissListener) {
this(context);
@@ -246,10 +286,10 @@
}
/**
- * Start showing a fast-track window for the given {@link Contacts#_ID}
- * pointing towards the given location.
+ * Start showing a dialog for the given {@link Contacts#_ID} pointing
+ * towards the given location.
*/
- public void show(Uri contactUri, Rect anchor, int mode, String[] excludeMimes) {
+ public void show(Uri lookupUri, Rect anchor, int mode, String[] excludeMimes) {
if (mShowing || mQuerying) {
Log.w(TAG, "already in process of showing");
return;
@@ -260,29 +300,61 @@
}
// Prepare header view for requested mode
+ mLookupUri = lookupUri;
+ mAnchor = new Rect(anchor);
mMode = mode;
- mHeader = getHeaderView(mode);
mExcludeMimes = excludeMimes;
+ mHeader = getHeaderView(mode);
+
setHeaderText(R.id.name, R.string.quickcontact_missing_name);
+
setHeaderText(R.id.status, null);
+ setHeaderText(R.id.timestamp, null);
+
setHeaderImage(R.id.presence, null);
+ setHeaderImage(R.id.source, null);
mHasValidSocial = false;
-
- mAggId = ContentUris.parseId(contactUri);
- mAnchor = new Rect(anchor);
mQuerying = true;
- Uri aggSummary = ContentUris.withAppendedId(Contacts.CONTENT_URI, mAggId);
- Uri aggSocial = ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mAggId);
- Uri aggData = Uri.withAppendedPath(aggSummary, Contacts.Data.CONTENT_DIRECTORY);
+ // Start background query for data, but only select photo rows when they
+ // directly match the super-primary PHOTO_ID.
+ final Uri dataUri = getDataUri(lookupUri);
+ mHandler.cancelOperation(TOKEN_DATA);
- // Start data query in background
- mHandler = new NotifyingAsyncQueryHandler(mContext, this);
- mHandler.startQuery(TOKEN_SUMMARY, null, aggSummary, SummaryQuery.PROJECTION, null, null, null);
- mHandler.startQuery(TOKEN_SOCIAL, null, aggSocial, SocialQuery.PROJECTION, null, null, null);
- mHandler.startQuery(TOKEN_DATA, null, aggData, DataQuery.PROJECTION, null, null, null);
+ // Only request photo data when required by mode
+ if (mMode == QuickContact.MODE_LARGE) {
+ // Select photos, but only super-primary
+ mHandler.startQuery(TOKEN_DATA, null, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
+ + "!=? OR (" + Data.MIMETYPE + "=? AND " + Data._ID + "=" + Contacts.PHOTO_ID
+ + ")", new String[] { Photo.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE }, null);
+ } else {
+ // Exclude all photos from cursor
+ mHandler.startQuery(TOKEN_DATA, null, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
+ + "!=?", new String[] { Photo.CONTENT_ITEM_TYPE }, null);
+ }
+ }
+
+ /**
+ * Build a {@link Uri} into the {@link Data} table for the requested
+ * {@link Contacts#CONTENT_LOOKUP_URI} style {@link Uri}.
+ */
+ private Uri getDataUri(Uri lookupUri) {
+ // TODO: Formalize method of extracting LOOKUP_KEY
+ final List<String> path = lookupUri.getPathSegments();
+ final boolean validLookup = path.size() >= 3 && "lookup".equals(path.get(1));
+ if (!validLookup) {
+ // We only accept valid lookup-style Uris
+ throw new IllegalArgumentException("Expecting lookup-style Uri");
+ } else if (path.size() == 3) {
+ // No direct _ID provided, so force a lookup
+ lookupUri = Contacts.lookupContact(mContext.getContentResolver(), lookupUri);
+ }
+
+ final long contactId = ContentUris.parseId(lookupUri);
+ return Uri.withAppendedPath(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId),
+ Contacts.Data.CONTENT_DIRECTORY);
}
/**
@@ -302,7 +374,7 @@
}
/**
- * Actual internal method to show this fast-track window. Called only by
+ * Actual internal method to show this dialog. Called only by
* {@link #considerShowing()} when all data requirements have been met.
*/
private void showInternal() {
@@ -347,66 +419,69 @@
if (TRACE_LAUNCH) {
android.os.Debug.stopMethodTracing();
+ Log.d(TAG, "Window recycled " + mWindowRecycled + " times, chiclets "
+ + mActionRecycled + " times");
}
}
/**
- * Dismiss this fast-track window if showing.
+ * Dismiss this dialog if showing.
*/
public void dismiss() {
+ // Notify any listeners that we've been dismissed
+ if (mDismissListener != null) {
+ mDismissListener.onDismiss(this);
+ }
+
if (!isShowing()) {
- Log.d(TAG, "not visible, ignore");
+ if (LOGD) Log.d(TAG, "not visible, ignore");
return;
}
boolean hadDecor = mDecor != null;
-
if (hadDecor) {
mWindowManager.removeView(mDecor);
mDecor = null;
mWindow.closeAllPanels();
}
- // Release refrence to last chiclet.
+ // Release reference to last chiclet.
mLastAction = null;
// Completely hide header from current mode
mHeader.setVisibility(View.GONE);
// Cancel any pending queries
- mHandler.cancelOperation(TOKEN_SUMMARY);
- mHandler.cancelOperation(TOKEN_SOCIAL);
mHandler.cancelOperation(TOKEN_DATA);
// Clear track actions and scroll to hard left
mResolveCache.clear();
mActions.clear();
- mTrack.removeViews(1, mTrack.getChildCount() - 2);
+
+ // Recycle any chiclets in use
+ while (mTrack.getChildCount() > 2) {
+ this.releaseView(mTrack.getChildAt(1));
+ mTrack.removeViewAt(1);
+ }
+
mTrackScroll.fullScroll(View.FOCUS_LEFT);
mWasDownArrow = false;
setResolveVisible(false, null);
mQuerying = false;
- mHasSummary = false;
- mHasSocial = false;
- mHasActions = false;
if (!hadDecor || !mShowing) {
- Log.d(TAG, "not showing, ignore");
+ if (LOGD) Log.d(TAG, "not showing, ignore");
return;
}
mShowing = false;
-
- // Notify any listeners that we've been dismissed
- if (mDismissListener != null) {
- mDismissListener.onDismiss(this);
- }
+ mWindowRecycled++;
}
/**
- * Returns true if this fast-track window is showing or querying.
+ * Returns true if this dialog is showing or querying.
*/
public boolean isShowing() {
return mShowing || mQuerying;
@@ -417,7 +492,7 @@
* {@link #showInternal()} when all data items are present.
*/
private synchronized void considerShowing() {
- if (mHasSummary && mHasSocial && mHasActions && !mShowing) {
+ if (mHasData && !mShowing) {
if (mMode == QuickContact.MODE_MEDIUM && !mHasValidSocial) {
// Missing valid social, swap medium for small header
mHeader.setVisibility(View.GONE);
@@ -438,20 +513,8 @@
return;
}
- switch (token) {
- case TOKEN_SUMMARY:
- handleSummary(cursor);
- mHasSummary = true;
- break;
- case TOKEN_SOCIAL:
- handleSocial(cursor);
- mHasSocial = true;
- break;
- case TOKEN_DATA:
- handleData(cursor);
- mHasActions = true;
- break;
- }
+ handleData(cursor);
+ mHasData = true;
if (!cursor.isClosed()) {
cursor.close();
@@ -470,6 +533,7 @@
final View view = mHeader.findViewById(id);
if (view instanceof TextView) {
((TextView)view).setText(value);
+ view.setVisibility(TextUtils.isEmpty(value) ? View.GONE : View.VISIBLE);
}
}
@@ -483,56 +547,28 @@
final View view = mHeader.findViewById(id);
if (view instanceof ImageView) {
((ImageView)view).setImageDrawable(drawable);
+ view.setVisibility(drawable == null ? View.GONE : View.VISIBLE);
}
}
/**
- * Handle the result from the {@link #TOKEN_SUMMARY} query.
- */
- private void handleSummary(Cursor cursor) {
- if (cursor == null || !cursor.moveToNext()) return;
-
- // TODO: switch to provider-specific presence dots instead of using
- // overall summary dot.
- final String name = cursor.getString(SummaryQuery.DISPLAY_NAME);
- final int status = cursor.getInt(SummaryQuery.CONTACT_PRESENCE);
- final Drawable statusIcon = getPresenceIcon(status);
-
- setHeaderText(R.id.name, name);
- setHeaderImage(R.id.presence, statusIcon);
- }
-
- /**
- * Handle the result from the {@link #TOKEN_SOCIAL} query.
- */
- private void handleSocial(Cursor cursor) {
- if (cursor == null || !cursor.moveToNext()) return;
-
- final String status = cursor.getString(SocialQuery.TITLE);
-
- mHasValidSocial = !TextUtils.isEmpty(status);
-
- setHeaderText(R.id.status, status);
- }
-
- /**
* Find the presence icon for showing in summary header.
*/
private Drawable getPresenceIcon(int status) {
int resId = -1;
switch (status) {
- case Presence.AVAILABLE:
+ case StatusUpdates.AVAILABLE:
resId = android.R.drawable.presence_online;
break;
- case Presence.IDLE:
- case Presence.AWAY:
+ case StatusUpdates.IDLE:
+ case StatusUpdates.AWAY:
resId = android.R.drawable.presence_away;
break;
- case Presence.DO_NOT_DISTURB:
+ case StatusUpdates.DO_NOT_DISTURB:
resId = android.R.drawable.presence_busy;
break;
}
- if (resId > 0) {
+ if (resId != -1) {
return mContext.getResources().getDrawable(resId);
} else {
return null;
@@ -540,25 +576,25 @@
}
/**
- * Find the Fast-Track-specific presence icon for showing in chiclets.
+ * Find the QuickContact-specific presence icon for showing in chiclets.
*/
private Drawable getTrackPresenceIcon(int status) {
int resId = -1;
switch (status) {
- case Presence.AVAILABLE:
+ case StatusUpdates.AVAILABLE:
resId = R.drawable.quickcontact_slider_presence_active;
break;
- case Presence.IDLE:
- case Presence.AWAY:
+ case StatusUpdates.IDLE:
+ case StatusUpdates.AWAY:
resId = R.drawable.quickcontact_slider_presence_away;
break;
- case Presence.DO_NOT_DISTURB:
+ case StatusUpdates.DO_NOT_DISTURB:
resId = R.drawable.quickcontact_slider_presence_busy;
break;
- case Presence.INVISIBLE:
+ case StatusUpdates.INVISIBLE:
resId = R.drawable.quickcontact_slider_presence_inactive;
break;
- case Presence.OFFLINE:
+ case StatusUpdates.OFFLINE:
default:
resId = R.drawable.quickcontact_slider_presence_inactive;
}
@@ -571,7 +607,7 @@
return cursor.getString(index);
}
- /** Read {@link int} from the given {@link Cursor}. */
+ /** Read {@link Integer} from the given {@link Cursor}. */
private static int getAsInt(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
return cursor.getInt(index);
@@ -602,7 +638,6 @@
* Returns a lookup (@link Uri) for the contact data item.
*/
public Uri getDataUri();
-
}
/**
@@ -671,11 +706,34 @@
mIntent = new Intent(Intent.ACTION_SENDTO, mailUri);
}
- } else {
+ } else if (Im.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(
+ getAsString(cursor, Data.MIMETYPE));
+ final int protocol = isEmail ? Im.PROTOCOL_GOOGLE_TALK :
+ getAsInt(cursor, Im.PROTOCOL);
+
+ String host = getAsString(cursor, Im.CUSTOM_PROTOCOL);
+ String data = getAsString(cursor, isEmail ? Email.DATA : Im.DATA);
+ if (protocol != Im.PROTOCOL_CUSTOM) {
+ // Try bringing in a well-known host for specific protocols
+ host = ContactsUtils.lookupProviderNameFromId(protocol);
+ }
+
+ if (!TextUtils.isEmpty(host) && !TextUtils.isEmpty(data)) {
+ final String authority = host.toLowerCase();
+ final Uri imUri = new Uri.Builder().scheme(Constants.SCHEME_IMTO).authority(
+ authority).appendPath(data).build();
+ mIntent = new Intent(Intent.ACTION_SENDTO, imUri);
+ }
+ }
+
+ if (mIntent == null) {
// Otherwise fall back to default VIEW action
mIntent = new Intent(Intent.ACTION_VIEW, mDataUri);
}
- mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Always launch as new task, since we're like a launcher
+ mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
/** {@inheritDoc} */
@@ -730,11 +788,11 @@
*/
private static class ProfileAction implements Action {
private final Context mContext;
- private final long mId;
+ private final Uri mLookupUri;
- public ProfileAction(Context context, long contactId) {
+ public ProfileAction(Context context, Uri lookupUri) {
mContext = context;
- mId = contactId;
+ mLookupUri = lookupUri;
}
/** {@inheritDoc} */
@@ -759,8 +817,7 @@
/** {@inheritDoc} */
public Intent getIntent() {
- final Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mId);
- final Intent intent = new Intent(Intent.ACTION_VIEW, contactUri);
+ final Intent intent = new Intent(Intent.ACTION_VIEW, mLookupUri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
@@ -816,8 +873,16 @@
final List<ResolveInfo> matches = mPackageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
- if (matches.size() > 0) {
- final ResolveInfo bestResolve = matches.get(0);
+ // Pick first match, otherwise best found
+ ResolveInfo bestResolve = null;
+ final int size = matches.size();
+ if (size == 1) {
+ bestResolve = matches.get(0);
+ } else if (size > 1) {
+ bestResolve = getBestResolve(matches);
+ }
+
+ if (bestResolve != null) {
final Drawable icon = bestResolve.loadIcon(mPackageManager);
entry.bestResolve = bestResolve;
@@ -830,6 +895,32 @@
}
/**
+ * Best {@link ResolveInfo} when multiple found. Ties are broken by
+ * selecting first from the {QuickContactWindow#sPreferResolve} list of
+ * preferred packages, second by apps that live on the system partition,
+ * otherwise the app from the top of the list. This is
+ * <strong>only</strong> used for selecting a default icon for
+ * displaying in the track, and does not shortcut the system
+ * {@link Intent} disambiguation dialog.
+ */
+ protected ResolveInfo getBestResolve(List<ResolveInfo> matches) {
+ // Accept any package from prefer list, otherwise first system app
+ ResolveInfo firstSystem = null;
+ for (ResolveInfo info : matches) {
+ final boolean isSystem = (info.activityInfo.applicationInfo.flags
+ & ApplicationInfo.FLAG_SYSTEM) != 0;
+ final boolean isPrefer = QuickContactWindow.sPreferResolve
+ .contains(info.activityInfo.applicationInfo.packageName);
+
+ if (isPrefer) return info;
+ if (isSystem && firstSystem != null) firstSystem = info;
+ }
+
+ // Return first system found, otherwise first from list
+ return firstSystem != null ? firstSystem : matches.get(0);
+ }
+
+ /**
* Check {@link PackageManager} to see if any apps offer to handle the
* given {@link Action}.
*/
@@ -906,6 +997,99 @@
}
/**
+ * Internal storage for the latest social status, as built when walking
+ * across a {@Link DataQuery} query. Will always keep record of at
+ * least the first status it encounters, but will replace it with newer
+ * statuses, as determined by timestamps.
+ */
+ private static class LatestStatus {
+ private String mStatus = null;
+ private long mTimestamp = -1;
+
+ private String mResPackage = null;
+ private int mIconRes = -1;
+ private int mLabelRes = -1;
+
+ private int getCursorInt(Cursor cursor, int columnIndex, int missingValue) {
+ if (cursor.isNull(columnIndex)) return missingValue;
+ return cursor.getInt(columnIndex);
+ }
+
+ /**
+ * Attempt updating this {@link LatestStatus} based on values at the
+ * current row of the given {@link Cursor}. Assumes that query
+ * projection was {@link DataQuery#PROJECTION}.
+ */
+ public void possibleUpdate(Cursor cursor) {
+ final boolean hasStatus = !cursor.isNull(DataQuery.STATUS);
+ final boolean hasTimestamp = !cursor.isNull(DataQuery.STATUS_TIMESTAMP);
+
+ // Bail early when not valid status, or when previous status was
+ // found and we can't compare this one.
+ if (!hasStatus) return;
+ if (isValid() && !hasTimestamp) return;
+
+ if (hasTimestamp) {
+ // Compare timestamps and bail if older status
+ final long newTimestamp = cursor.getLong(DataQuery.STATUS_TIMESTAMP);
+ if (newTimestamp < mTimestamp) return;
+
+ mTimestamp = newTimestamp;
+ }
+
+ // Fill in remaining details from cursor
+ mStatus = cursor.getString(DataQuery.STATUS);
+ mResPackage = cursor.getString(DataQuery.STATUS_RES_PACKAGE);
+ mIconRes = getCursorInt(cursor, DataQuery.STATUS_ICON, -1);
+ mLabelRes = getCursorInt(cursor, DataQuery.STATUS_LABEL, -1);
+ }
+
+ public boolean isValid() {
+ return !TextUtils.isEmpty(mStatus);
+ }
+
+ public CharSequence getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Build any timestamp and label into a single string.
+ */
+ public CharSequence getTimestampLabel(Context context) {
+ final PackageManager pm = context.getPackageManager();
+
+ final boolean validTimestamp = mTimestamp > 0;
+ final boolean validLabel = mResPackage != null && mLabelRes != -1;
+
+ final CharSequence timeClause = validTimestamp ? DateUtils.getRelativeTimeSpanString(
+ mTimestamp, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS,
+ DateUtils.FORMAT_ABBREV_RELATIVE) : null;
+ final CharSequence labelClause = validLabel ? pm.getText(mResPackage, mLabelRes,
+ null) : null;
+
+ if (validTimestamp && validLabel) {
+ return context.getString(
+ com.android.internal.R.string.contact_status_update_attribution_with_date,
+ timeClause, labelClause);
+ } else if (validLabel) {
+ return context.getString(
+ com.android.internal.R.string.contact_status_update_attribution,
+ labelClause);
+ } else if (validTimestamp) {
+ return timeClause;
+ } else {
+ return null;
+ }
+ }
+
+ public Drawable getIcon(Context context) {
+ final PackageManager pm = context.getPackageManager();
+ final boolean validIcon = mResPackage != null && mIconRes != -1;
+ return validIcon ? pm.getDrawable(mResPackage, mIconRes, null) : null;
+ }
+ }
+
+ /**
* Handle the result from the {@link #TOKEN_DATA} query.
*/
private void handleData(Cursor cursor) {
@@ -913,37 +1097,36 @@
if (!isMimeExcluded(Contacts.CONTENT_ITEM_TYPE)) {
// Add the profile shortcut action
- final Action action = new ProfileAction(mContext, mAggId);
+ final Action action = new ProfileAction(mContext, mLookupUri);
mActions.collect(Contacts.CONTENT_ITEM_TYPE, action);
}
+ final LatestStatus status = new LatestStatus();
final Sources sources = Sources.getInstance(mContext);
final ImageView photoView = (ImageView)mHeader.findViewById(R.id.photo);
+ Bitmap photoBitmap = null;
while (cursor.moveToNext()) {
+ final long dataId = cursor.getLong(DataQuery._ID);
final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE);
final String resPackage = cursor.getString(DataQuery.RES_PACKAGE);
final String mimeType = cursor.getString(DataQuery.MIMETYPE);
- final long dataId = cursor.getLong(DataQuery._ID);
+
+ // Handle any social status updates from this row
+ status.possibleUpdate(cursor);
// Skip this data item if MIME-type excluded
if (isMimeExcluded(mimeType)) continue;
- // Handle when a photo appears in the various data items
- // TODO: accept a photo only if its marked as primary
- // TODO: move to using photo thumbnail columns, when they exist
- // TODO: launch photo as separate TOKEN query, only for large
-// if (photoView != null && Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
-// final int colPhoto = cursor.getColumnIndex(Photo.PHOTO);
-// final byte[] photoBlob = cursor.getBlob(colPhoto);
-// final Bitmap photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0,
-// photoBlob.length);
-// photoView.setImageBitmap(photoBitmap);
-// continue;
-// }
-
- // TODO: find the ContactsSource for this, either from accountType,
- // or through lazy-loading when resPackage is set, or default.
+ // Handle photos included as data row
+ if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final int colPhoto = cursor.getColumnIndex(Photo.PHOTO);
+ final byte[] photoBlob = cursor.getBlob(colPhoto);
+ if (photoBlob != null) {
+ photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
+ }
+ continue;
+ }
final DataKind kind = sources.getKindOrFallback(accountType, mimeType, mContext,
ContactsSource.LEVEL_MIMETYPES);
@@ -962,6 +1145,51 @@
kind, dataId, cursor);
considerAdd(action, Constants.MIME_SMS_ADDRESS);
}
+
+ // Handle Email rows with presence data as Im entry
+ final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
+ if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final DataKind imKind = sources.getKindOrFallback(accountType,
+ Im.CONTENT_ITEM_TYPE, mContext, ContactsSource.LEVEL_MIMETYPES);
+ if (imKind != null) {
+ final Action action = new DataAction(mContext, Im.CONTENT_ITEM_TYPE, imKind,
+ dataId, cursor);
+ considerAdd(action, Im.CONTENT_ITEM_TYPE);
+ }
+ }
+ }
+
+ if (cursor.moveToLast()) {
+ // Read contact information from last data row
+ final String name = cursor.getString(DataQuery.DISPLAY_NAME);
+ final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE);
+ final Drawable statusIcon = getPresenceIcon(presence);
+
+ setHeaderText(R.id.name, name);
+ setHeaderImage(R.id.presence, statusIcon);
+ }
+
+ if (photoView != null) {
+ // Place photo when discovered in data, otherwise hide
+ photoView.setVisibility(photoBitmap != null ? View.VISIBLE : View.GONE);
+ photoView.setImageBitmap(photoBitmap);
+ }
+
+ mHasValidSocial = status.isValid();
+ if (mHasValidSocial && mMode != QuickContact.MODE_SMALL) {
+ // Update status when valid was found
+ setHeaderText(R.id.status, status.getStatus());
+ setHeaderText(R.id.timestamp, status.getTimestampLabel(mContext));
+
+ final Drawable icon = status.getIcon(mContext);
+ setHeaderImage(R.id.source, icon);
+
+ if (mMode == QuickContact.MODE_MEDIUM) {
+ // Hide medium divider when missing icon
+ final boolean validIcon = icon != null;
+ mHeader.findViewById(R.id.source_divider).setVisibility(
+ validIcon ? View.VISIBLE : View.GONE);
+ }
}
// Turn our list of actions into UI elements, starting with common types
@@ -995,12 +1223,34 @@
}
/**
+ * Obtain a new {@link CheckableImageView} for a new chiclet, either by
+ * recycling one from {@link #mActionPool}, or by inflating a new one. When
+ * finished, use {@link #releaseView(View)} to return back into the pool for
+ * later recycling.
+ */
+ private synchronized View obtainView() {
+ View view = mActionPool.poll();
+ if (view == null || QuickContactActivity.FORCE_CREATE) {
+ view = mInflater.inflate(R.layout.quickcontact_item, mTrack, false);
+ }
+ return view;
+ }
+
+ /**
+ * Return the given {@link CheckableImageView} into our internal pool for
+ * possible recycling during another pass.
+ */
+ private synchronized void releaseView(View view) {
+ mActionPool.offer(view);
+ mActionRecycled++;
+ }
+
+ /**
* Inflate the in-track view for the action of the given MIME-type. Will use
* the icon provided by the {@link DataKind}.
*/
private View inflateAction(String mimeType) {
- CheckableImageView view = (CheckableImageView)mInflater.inflate(
- R.layout.quickcontact_item, mTrack, false);
+ final CheckableImageView view = (CheckableImageView)obtainView();
boolean isActionSet = false;
// Add direct intent if single child, otherwise flag for multiple
@@ -1009,12 +1259,12 @@
if (children.size() == 1) {
view.setTag(firstInfo);
} else {
- for (Action action: children) {
- if (action.isPrimary()) {
- view.setTag(action);
- isActionSet = true;
- break;
- }
+ for (Action action : children) {
+ if (action.isPrimary()) {
+ view.setTag(action);
+ isActionSet = true;
+ break;
+ }
}
if (!isActionSet) {
view.setTag(children);
@@ -1024,6 +1274,7 @@
// Set icon and listen for clicks
final CharSequence descrip = mResolveCache.getDescription(firstInfo);
final Drawable icon = mResolveCache.getIcon(firstInfo);
+ view.setChecked(false);
view.setContentDescription(descrip);
view.setImageDrawable(icon);
view.setOnClickListener(this);
@@ -1038,8 +1289,8 @@
/**
* Flag indicating if {@link #mArrowDown} was visible during the last call
- * to {@link #setResolveVisible(boolean)}. Used to decide during a later
- * call if the arrow should be restored.
+ * to {@link #setResolveVisible(boolean, CheckableImageView)}. Used to
+ * decide during a later call if the arrow should be restored.
*/
private boolean mWasDownArrow = false;
@@ -1151,20 +1402,54 @@
mMakePrimary = isChecked;
}
+ private void onBackPressed() {
+ // Back key will first dismiss any expanded resolve list, otherwise
+ // it will close the entire dialog.
+ if (mFooterDisambig.getVisibility() == View.VISIBLE) {
+ setResolveVisible(false, null);
+ } else {
+ dismiss();
+ }
+ }
+
/** {@inheritDoc} */
public boolean dispatchKeyEvent(KeyEvent event) {
- if (event.getAction() == KeyEvent.ACTION_DOWN
- && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- // Back key will first dismiss any expanded resolve list, otherwise
- // it will close the entire dialog.
- if (mFooterDisambig.getVisibility() == View.VISIBLE) {
- setResolveVisible(false, null);
- } else {
- dismiss();
- }
+ if (mWindow.superDispatchKeyEvent(event)) {
return true;
}
- return mWindow.superDispatchKeyEvent(event);
+ return event.dispatch(this, mDecor != null
+ ? mDecor.getKeyDispatcherState() : null, this);
+ }
+
+ /** {@inheritDoc} */
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ event.startTracking();
+ return true;
+ }
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
+ && !event.isCanceled()) {
+ onBackPressed();
+ return true;
+ }
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+ return false;
}
/** {@inheritDoc} */
@@ -1181,8 +1466,8 @@
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Only try detecting outside events on down-press
mDecor.getHitRect(mRect);
- mRect.top = mRect.top + mDecor.getPaddingTop();
- mRect.bottom = mRect.bottom - mDecor.getPaddingBottom();
+ mRect.top = mRect.top + mDecor.getPaddingTop();
+ mRect.bottom = mRect.bottom - mDecor.getPaddingBottom();
final int x = (int)event.getX();
final int y = (int)event.getY();
if (!mRect.contains(x, y)) {
@@ -1197,8 +1482,9 @@
if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
dismiss();
return true;
+ } else {
+ return mWindow.superDispatchTouchEvent(event);
}
- return mWindow.superDispatchTouchEvent(event);
}
/** {@inheritDoc} */
@@ -1270,49 +1556,50 @@
// No actions
}
- private interface SummaryQuery {
- final String[] PROJECTION = new String[] {
- Contacts.DISPLAY_NAME,
- Contacts.PHOTO_ID,
- Contacts.CONTACT_PRESENCE,
- Contacts.CONTACT_STATUS,
- };
-
- final int DISPLAY_NAME = 0;
- final int PHOTO_ID = 1;
- final int CONTACT_PRESENCE = 2;
- final int CONTACT_STATUS = 3;
- }
-
- private interface SocialQuery {
- final String[] PROJECTION = new String[] {
- Activities.PUBLISHED,
- Activities.TITLE,
- };
-
- final int PUBLISHED = 0;
- final int TITLE = 1;
- }
-
private interface DataQuery {
final String[] PROJECTION = new String[] {
Data._ID,
+
RawContacts.ACCOUNT_TYPE,
+ Contacts.STARRED,
+ Contacts.DISPLAY_NAME,
+ Contacts.CONTACT_PRESENCE,
+
+ Data.STATUS,
+ Data.STATUS_RES_PACKAGE,
+ Data.STATUS_ICON,
+ Data.STATUS_LABEL,
+ Data.STATUS_TIMESTAMP,
+ Data.PRESENCE,
+
Data.RES_PACKAGE,
Data.MIMETYPE,
Data.IS_PRIMARY,
Data.IS_SUPER_PRIMARY,
Data.RAW_CONTACT_ID,
+
Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11,
Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
};
final int _ID = 0;
+
final int ACCOUNT_TYPE = 1;
- final int RES_PACKAGE = 2;
- final int MIMETYPE = 3;
- final int IS_PRIMARY = 4;
- final int IS_SUPER_PRIMARY = 5;
+ final int STARRED = 2;
+ final int DISPLAY_NAME = 3;
+ final int CONTACT_PRESENCE = 4;
+
+ final int STATUS = 5;
+ final int STATUS_RES_PACKAGE = 6;
+ final int STATUS_ICON = 7;
+ final int STATUS_LABEL = 8;
+ final int STATUS_TIMESTAMP = 9;
+ final int PRESENCE = 10;
+
+ final int RES_PACKAGE = 11;
+ final int MIMETYPE = 12;
+ final int IS_PRIMARY = 13;
+ final int IS_SUPER_PRIMARY = 14;
}
}
diff --git a/src/com/android/contacts/ui/widget/ContactEditorView.java b/src/com/android/contacts/ui/widget/ContactEditorView.java
index c723f6f..8e76e7b 100644
--- a/src/com/android/contacts/ui/widget/ContactEditorView.java
+++ b/src/com/android/contacts/ui/widget/ContactEditorView.java
@@ -18,6 +18,7 @@
import com.android.contacts.R;
import com.android.contacts.model.ContactsSource;
+import com.android.contacts.model.Editor;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityModifier;
import com.android.contacts.model.ContactsSource.DataKind;
@@ -35,12 +36,14 @@
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
-import android.widget.RelativeLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.TextView;
/**
@@ -54,7 +57,7 @@
* adding {@link Data} rows or changing {@link EditType}, are performed through
* {@link EntityModifier} to ensure that {@link ContactsSource} are enforced.
*/
-public class ContactEditorView extends RelativeLayout implements OnClickListener {
+public class ContactEditorView extends LinearLayout implements OnClickListener {
private LayoutInflater mInflater;
private TextView mReadOnly;
@@ -72,6 +75,14 @@
private Drawable mSecondaryOpen;
private Drawable mSecondaryClosed;
+ private View mHeader;
+ private View mSideBar;
+ private ImageView mHeaderIcon;
+ private TextView mHeaderAccountType;
+ private TextView mHeaderAccountName;
+
+ private long mRawContactId = -1;
+
public ContactEditorView(Context context) {
super(context);
}
@@ -101,6 +112,12 @@
mGeneral = (ViewGroup)findViewById(R.id.sect_general);
mSecondary = (ViewGroup)findViewById(R.id.sect_secondary);
+ mHeader = findViewById(R.id.header);
+ mSideBar = findViewById(R.id.color_bar);
+ mHeaderIcon = (ImageView) findViewById(R.id.header_icon);
+ mHeaderAccountType = (TextView) findViewById(R.id.header_account_type);
+ mHeaderAccountName = (TextView) findViewById(R.id.header_account_name);
+
mSecondaryHeader = (TextView)findViewById(R.id.head_secondary);
mSecondaryHeader.setOnClickListener(this);
@@ -170,6 +187,21 @@
// Make sure we have StructuredName
EntityModifier.ensureKindExists(state, source, StructuredName.CONTENT_ITEM_TYPE);
+ // Fill in the header info
+ mHeader.setBackgroundColor(source.getHeaderColor(mContext));
+ mSideBar.setBackgroundColor(source.getSideBarColor(mContext));
+ ValuesDelta values = state.getValues();
+ String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
+ if (TextUtils.isEmpty(accountName)) {
+ // TODO get from resource
+ accountName = "Local contact";
+ }
+ mHeaderAccountName.setText(accountName);
+ mHeaderAccountType.setText(source.getDisplayLabel(mContext));
+ mHeaderIcon.setImageDrawable(source.getDisplayIcon(mContext));
+
+ mRawContactId = values.getAsLong(RawContacts._ID);
+
// Show photo editor when supported
EntityModifier.ensureKindExists(state, source, Photo.CONTENT_ITEM_TYPE);
mHasPhotoEditor = (source.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null);
@@ -177,7 +209,14 @@
mPhoto.setEnabled(!source.readOnly);
mName.setEnabled(!source.readOnly);
- mReadOnly.setVisibility(source.readOnly ? View.VISIBLE : View.GONE);
+ boolean readOnly = source.readOnly;
+ if (readOnly) {
+ mGeneral.setVisibility(View.GONE);
+ mSecondary.setVisibility(View.GONE);
+ mSecondaryHeader.setVisibility(View.GONE);
+ } else {
+ mReadOnly.setVisibility(View.GONE);
+ }
// Create editor sections for each possible data kind
for (DataKind kind : source.getSortedDataKinds()) {
@@ -193,7 +232,7 @@
// Handle special case editor for photos
final ValuesDelta primary = state.getPrimaryEntry(mimeType);
mPhoto.setValues(kind, primary, state, source.readOnly);
- } else {
+ } else if (!readOnly) {
// Otherwise use generic section-based editors
if (kind.fieldList == null) continue;
final ViewGroup parent = kind.secondary ? mSecondary : mGeneral;
@@ -215,4 +254,8 @@
public void setNameEditorListener(EditorListener listener) {
mName.setEditorListener(listener);
}
+
+ public long getRawContactId() {
+ return mRawContactId;
+ }
}
diff --git a/src/com/android/contacts/util/Constants.java b/src/com/android/contacts/util/Constants.java
index 696717e..e0178ad 100644
--- a/src/com/android/contacts/util/Constants.java
+++ b/src/com/android/contacts/util/Constants.java
@@ -34,5 +34,6 @@
public static final String SCHEME_TEL = "tel";
public static final String SCHEME_SMSTO = "smsto";
public static final String SCHEME_MAILTO = "mailto";
+ public static final String SCHEME_IMTO = "imto";
}
diff --git a/tests/src/com/android/contacts/EntityModifierTests.java b/tests/src/com/android/contacts/EntityModifierTests.java
index 1de3936..5f7e0ef 100644
--- a/tests/src/com/android/contacts/EntityModifierTests.java
+++ b/tests/src/com/android/contacts/EntityModifierTests.java
@@ -90,6 +90,16 @@
addKind(kind);
}
+
+ @Override
+ public int getHeaderColor(Context context) {
+ return 0;
+ }
+
+ @Override
+ public int getSideBarColor(Context context) {
+ return 0xffffff;
+ }
}
/**