am afcedddd: (-s ours) am 59b5dfa3: Import revised translations. DO NOT MERGE
* commit 'afcedddd7ae41323174f7fdb158c159c8c2a3461':
Import revised translations. DO NOT MERGE
diff --git a/Android.mk b/Android.mk
index ff1b7e2..1c9dcc4 100644
--- a/Android.mk
+++ b/Android.mk
@@ -5,7 +5,11 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := com.android.phone.common com.android.vcard android-common
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ com.android.phone.common \
+ com.android.vcard \
+ android-common \
+ guava
LOCAL_PACKAGE_NAME := Contacts
LOCAL_CERTIFICATE := shared
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 52562e0..47340a0 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -46,7 +46,7 @@
>
<!-- A virtual 12 key dialer -->
- <activity android:name="TwelveKeyDialer"
+ <activity android:name=".activities.DialpadActivity"
android:launchMode="singleTop"
>
<intent-filter>
@@ -57,7 +57,7 @@
</activity>
<!-- A list of recent calls -->
- <activity android:name="RecentCallsListActivity"
+ <activity android:name=".activities.CallLogActivity"
android:label="@string/recentCallsIconLabel"
>
<intent-filter>
@@ -119,7 +119,7 @@
</activity>
<!-- Tab container for all tabs -->
- <activity android:name="DialtactsActivity"
+ <activity android:name=".activities.DialtactsActivity"
android:label="@string/launcherDialer"
android:theme="@style/DialtactsTheme"
android:launchMode="singleTask"
@@ -127,6 +127,7 @@
android:icon="@mipmap/ic_launcher_phone"
android:screenOrientation="nosensor"
android:enabled="@*android:bool/config_voice_capable"
+ android:taskAffinity="android.task.contacts.phone"
>
<intent-filter>
<action android:name="android.intent.action.DIAL" />
@@ -171,11 +172,10 @@
</intent-filter>
</activity>
- <!-- Front door proxy that picks the right UI based on the screen config -->
- <activity android:name=".activities.ContactsFrontDoor"
- android:label="@string/contactsList"
- android:icon="@mipmap/ic_launcher_contacts"
- android:theme="@style/ContactBrowserTheme"
+ <!-- The main Contacts activity with the contact list, favorites, and groups. -->
+ <activity android:name=".activities.PeopleActivity"
+ android:label="@string/people"
+ android:theme="@style/PeopleTheme"
android:clearTaskOnLaunch="true"
android:launchMode="singleTop"
>
@@ -185,25 +185,6 @@
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
-
- <intent-filter>
- <action android:name="android.intent.action.VIEW" />
- <category android:name="android.intent.category.DEFAULT" />
- <data android:mimeType="vnd.android.cursor.dir/person" />
- <data android:mimeType="vnd.android.cursor.dir/contact" />
- <data android:mimeType="vnd.android.cursor.item/person" />
- <data android:mimeType="vnd.android.cursor.item/contact" />
- <data android:mimeType="vnd.android.cursor.item/raw_contact" />
- </intent-filter>
- </activity>
-
- <!-- The actual list of contacts -->
- <activity android:name=".activities.ContactBrowserActivity"
- android:label="@string/contactsList"
- android:theme="@style/ContactBrowserTheme"
- android:launchMode="singleTop"
- android:clearTaskOnLaunch="true"
- >
<intent-filter>
<action android:name="com.android.contacts.action.LIST_DEFAULT" />
<category android:name="android.intent.category.DEFAULT" />
@@ -291,6 +272,7 @@
<data android:mimeType="vnd.android.cursor.dir/phone" />
<data android:mimeType="vnd.android.cursor.dir/postal-address_v2" />
<data android:mimeType="vnd.android.cursor.dir/postal-address" />
+ <data android:mimeType="vnd.android.cursor.dir/email_v2" />
</intent-filter>
<intent-filter>
@@ -307,7 +289,7 @@
<!-- Backwards compatibility: somebody may have hard coded this activity name -->
<activity-alias android:name="ContactsListActivity"
- android:targetActivity=".activities.ContactBrowserActivity"
+ android:targetActivity=".activities.PeopleActivity"
/>
<!-- An activity for joining contacts -->
@@ -335,7 +317,7 @@
<activity
android:name=".activities.ShowOrCreateActivity"
- android:theme="@style/FullyTranslucent">
+ android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="com.android.contacts.action.SHOW_OR_CREATE_CONTACT" />
@@ -345,16 +327,36 @@
</intent-filter>
</activity>
+
+ <!-- List of groups -->
+ <activity android:name=".activities.GroupBrowserActivity"
+ android:label="@string/contactsGroupsLabel"
+ android:theme="@style/PeopleTheme"
+ android:launchMode="singleTop"
+ android:clearTaskOnLaunch="true">
+ <!-- TODO: Remove this temporary intent action name when the fragmentization
+ work is done. -->
+ <intent-filter>
+ <action android:name="com.android.phone.action.GROUPS_LIST" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.TAB" />
+ </intent-filter>
+ </activity>
+
+ <!-- Views the details of a single group -->
+ <activity android:name=".activities.GroupDetailActivity"
+ android:label=""
+ android:theme="@style/GroupDetailTheme" />
+
<!-- Used to show QuickContact window over a translucent activity, which is a
temporary hack until we add better framework support. -->
<activity
- android:name=".quickcontact.QuickContactActivity"
- android:theme="@style/FullyTranslucent.QuickContact"
+ android:name=".quickcontact.QuickContactWindow"
+ android:theme="@style/Theme.QuickContact"
android:launchMode="singleTop"
android:excludeFromRecents="true"
android:taskAffinity="android.task.quickcontact"
- android:windowSoftInputMode="stateUnchanged"
- >
+ android:windowSoftInputMode="stateUnchanged">
<intent-filter>
<action android:name="com.android.contacts.action.QUICK_CONTACT" />
@@ -426,6 +428,7 @@
<activity android:name="CallDetailActivity"
android:label="@string/callDetailTitle"
android:theme="@style/CallDetailActivityTheme"
+ android:taskAffinity="android.task.contacts.phone"
>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -442,6 +445,11 @@
<intent-filter android:label="@string/viewContactDesription">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.dir/person" />
+ <data android:mimeType="vnd.android.cursor.dir/contact" />
+ <data android:mimeType="vnd.android.cursor.item/person" />
+ <data android:mimeType="vnd.android.cursor.item/contact" />
+ <data android:mimeType="vnd.android.cursor.item/raw_contact" />
</intent-filter>
</activity>
@@ -511,10 +519,10 @@
android:theme="@android:style/Theme.Translucent">
</activity>
- <!-- Makes .ContactBrowserActivity the search target for any activity in Contacts -->
+ <!-- Makes .PeopleActivity the search target for any activity in Contacts -->
<meta-data
android:name="android.app.default_searchable"
- android:value=".activities.ContactBrowserActivity" />
+ android:value=".activities.PeopleActivity" />
<!-- LIVE FOLDERS -->
@@ -550,7 +558,7 @@
<!-- vCard related -->
<activity android:name=".vcard.ImportVCardActivity"
- android:configChanges="orientation"
+ android:configChanges="orientation|screenSize|keyboardHidden"
android:theme="@style/BackgroundOnly">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
diff --git a/res/drawable-hdpi/divider_horizontal_light.png b/res/drawable-hdpi/divider_horizontal_light.png
new file mode 100644
index 0000000..20d7a01
--- /dev/null
+++ b/res/drawable-hdpi/divider_horizontal_light.png
Binary files differ
diff --git a/res/drawable-sw580dp-hdpi/panel_message.9.png b/res/drawable-hdpi/panel_message.9.png
similarity index 100%
rename from res/drawable-sw580dp-hdpi/panel_message.9.png
rename to res/drawable-hdpi/panel_message.9.png
Binary files differ
diff --git a/res/drawable-mdpi/divider_horizontal_light.png b/res/drawable-mdpi/divider_horizontal_light.png
new file mode 100644
index 0000000..20d7a01
--- /dev/null
+++ b/res/drawable-mdpi/divider_horizontal_light.png
Binary files differ
diff --git a/res/drawable-sw580dp-mdpi/panel_message.9.png b/res/drawable-mdpi/panel_message.9.png
similarity index 100%
rename from res/drawable-sw580dp-mdpi/panel_message.9.png
rename to res/drawable-mdpi/panel_message.9.png
Binary files differ
diff --git a/res/drawable-sw580dp-nodpi/divider_vertical_dark.9.png b/res/drawable-xlarge-nodpi/divider_vertical_dark.9.png
similarity index 100%
rename from res/drawable-sw580dp-nodpi/divider_vertical_dark.9.png
rename to res/drawable-xlarge-nodpi/divider_vertical_dark.9.png
Binary files differ
diff --git a/res/drawable/quickactions_arrow_left_holo_light.xml b/res/drawable/quickactions_arrow_left_holo_light.xml
new file mode 100644
index 0000000..c1e18bd
--- /dev/null
+++ b/res/drawable/quickactions_arrow_left_holo_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_left_holo_light" />
+ <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_left_holo_light" />
+ <!-- TODO: provide callout-less state -->
+ <item android:drawable="@drawable/quickactions_arrowup_left_holo_light" />
+</selector>
diff --git a/res/drawable/quickactions_arrow_middle_holo_light.xml b/res/drawable/quickactions_arrow_middle_holo_light.xml
new file mode 100644
index 0000000..f88b513
--- /dev/null
+++ b/res/drawable/quickactions_arrow_middle_holo_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_middle_holo_light" />
+ <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_middle_holo_light" />
+ <!-- TODO: provide callout-less state -->
+ <item android:drawable="@drawable/quickactions_arrowup_middle_holo_light" />
+</selector>
diff --git a/res/drawable/quickactions_arrow_right_holo_light.xml b/res/drawable/quickactions_arrow_right_holo_light.xml
new file mode 100644
index 0000000..3e309fe
--- /dev/null
+++ b/res/drawable/quickactions_arrow_right_holo_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_right_holo_light" />
+ <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_right_holo_light" />
+ <!-- TODO: provide callout-less state -->
+ <item android:drawable="@drawable/quickactions_arrowup_right_holo_light" />
+</selector>
diff --git a/res/layout-land/twelve_key_dialer.xml b/res/layout-land/dialpad_fragment.xml
similarity index 97%
rename from res/layout-land/twelve_key_dialer.xml
rename to res/layout-land/dialpad_fragment.xml
index 985d047..fe9fb28 100644
--- a/res/layout-land/twelve_key_dialer.xml
+++ b/res/layout-land/dialpad_fragment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/res/layout-sw580dp/contact_detail_header_view.xml b/res/layout-large/contact_detail_header_view.xml
similarity index 87%
rename from res/layout-sw580dp/contact_detail_header_view.xml
rename to res/layout-large/contact_detail_header_view.xml
index 52c21eb..19132dd 100644
--- a/res/layout-sw580dp/contact_detail_header_view.xml
+++ b/res/layout-large/contact_detail_header_view.xml
@@ -25,7 +25,7 @@
<TextView
android:id="@+id/attribution"
android:layout_width="match_parent"
- android:layout_height="@dimen/detail_header_attribution_height"
+ android:layout_height="56dip"
android:paddingRight="24dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorTertiary"
@@ -39,7 +39,7 @@
<ImageView
android:id="@+id/photo"
- android:layout_marginLeft="@dimen/detail_header_view_margin"
+ android:layout_marginLeft="16dip"
android:layout_width="96dip"
android:layout_height="96dip" />
@@ -60,7 +60,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="16dip"
- android:layout_marginLeft="@dimen/detail_header_view_margin">
+ android:layout_marginLeft="16dip">
<!-- Star -->
<CheckBox
@@ -77,24 +77,31 @@
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:paddingLeft="@dimen/detail_header_view_margin"
+ android:paddingLeft="16dip"
android:orientation="vertical">
<TextView
android:id="@+id/name"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
android:textSize="@dimen/contact_name_text_size" />
<TextView
android:id="@+id/phonetic_name"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:ellipsize="end"
android:layout_marginTop="-2dip"
android:visibility="gone" />
<TextView
android:id="@+id/organization"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginTop="-2dip"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/res/layout-long-land/twelve_key_dialer.xml b/res/layout-long-land/dialpad_fragment.xml
similarity index 97%
rename from res/layout-long-land/twelve_key_dialer.xml
rename to res/layout-long-land/dialpad_fragment.xml
index 1cf9690..f287741 100644
--- a/res/layout-long-land/twelve_key_dialer.xml
+++ b/res/layout-long-land/dialpad_fragment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/res/layout-long/twelve_key_dialer.xml b/res/layout-long/dialpad_fragment.xml
similarity index 88%
rename from res/layout-long/twelve_key_dialer.xml
rename to res/layout-long/dialpad_fragment.xml
index bd90df4..85250e2 100644
--- a/res/layout-long/twelve_key_dialer.xml
+++ b/res/layout-long/dialpad_fragment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,11 +14,14 @@
limitations under the License.
-->
+<!-- TODO (stopship) We don't want to specify a background color here. For now we just
+keep it because otherwise the dialer needs some imagination to use (white on white) -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:background="@android:color/black"
>
<!-- Text field above the keypad where the digits are displayed.
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_empty.xml b/res/layout-sw580dp-w1000dp/contact_detail_empty.xml
deleted file mode 100644
index 51ea04c..0000000
--- a/res/layout-sw580dp-w1000dp/contact_detail_empty.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Placeholder for empty details for a contact -->
-
-<com.android.contacts.widget.InterpolatingLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/emptyText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- ex:layout_wideParentWidth="800dip"
- ex:layout_wideMarginLeft="80dip"
- ex:layout_narrowParentWidth="500dip"
- ex:layout_narrowMarginLeft="44dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
- />
-</com.android.contacts.widget.InterpolatingLayout>
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml b/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml
deleted file mode 100644
index 529059a..0000000
--- a/res/layout-sw580dp-w1000dp/contact_detail_list_item.xml
+++ /dev/null
@@ -1,134 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <!-- Longer separating line (between kinds) -->
- <View
- android:id="@+id/kind_divider"
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@drawable/list_item_divider_holo" />
-
- <!-- Shorter separating line if there was no kind-separator -->
- <View
- android:id="@+id/in_kind_divider"
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:layout_marginLeft="164dip"
- android:background="@drawable/list_item_divider_holo" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:orientation="vertical"
- android:minHeight="@dimen/detail_min_line_item_height">
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_gravity="center_vertical">
- <TextView
- android:id="@+id/kind"
- android:layout_width="164dip"
- android:layout_height="@dimen/detail_min_line_item_height"
- android:paddingLeft="19dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorTertiary"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="center_vertical" />
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:paddingLeft="12dip"
- android:orientation="vertical">
- <TextView
- android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium" />
- <TextView
- android:id="@+id/footer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone" />
- </LinearLayout>
- <TextView
- android:id="@+id/type"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/detail_min_line_item_height"
- android:maxWidth="150dip"
- android:gravity="right|center_vertical"
- android:textColor="@color/detail_item_type_color"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <ImageView
- android:id="@+id/presence_icon"
- android:layout_width="32dip"
- android:layout_height="@dimen/detail_min_line_item_height"
- android:layout_marginLeft="5dip"
- android:gravity="center"
- android:scaleType="centerInside" />
-
- <ImageView
- android:id="@+id/action_icon"
- android:layout_width="32dip"
- android:layout_height="@dimen/detail_min_line_item_height"
- android:layout_marginLeft="16dip"
- android:layout_gravity="center_vertical"
- android:scaleType="centerInside" />
-
- <View
- android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_marginLeft="14dip"
- android:layout_marginRight="14dip"
- android:background="?android:attr/dividerVertical" />
-
- <ImageView
- android:id="@+id/secondary_action_button"
- android:layout_width="32dip"
- android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:gravity="center"
- android:scaleType="center"
- android:background="?android:attr/selectableItemBackground" />
- </LinearLayout>
- </LinearLayout>
-
- <!-- Longer separating line (only for the last row) -->
- <View
- android:id="@+id/line_below_last"
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@drawable/list_item_divider_holo" />
-</LinearLayout>
diff --git a/res/layout-sw580dp/item_kind_section.xml b/res/layout-sw580dp/item_kind_section.xml
deleted file mode 100644
index eaae563..0000000
--- a/res/layout-sw580dp/item_kind_section.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- the body surrounding all editors for a specific kind -->
-
-<com.android.contacts.editor.KindSectionView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <TextView
- android:id="@+id/kind_title"
- android:layout_width="@dimen/editor_title_label_width"
- android:layout_height="@dimen/editor_min_line_item_height"
- android:gravity="center_vertical"
- android:textColor="#7F7F7F"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- android:ellipsize="marquee" />
-
- <LinearLayout
- android:id="@+id/kind_editors"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_gravity="bottom"
- android:orientation="vertical" />
-
- <FrameLayout
- android:id="@+id/kind_plus_container"
- android:layout_width="wrap_content"
- android:layout_height="@dimen/editor_min_line_item_height">
- <ImageButton
- android:id="@+id/kind_plus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingLeft="@dimen/editor_round_button_padding_left"
- android:paddingRight="@dimen/editor_round_button_padding_right"
- android:paddingTop="@dimen/editor_round_button_padding_top"
- android:paddingBottom="@dimen/editor_round_button_padding_bottom"
- android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_menu_add_field_holo_light"
- android:contentDescription="@string/description_plus_button" />
- </FrameLayout>
-</com.android.contacts.editor.KindSectionView>
diff --git a/res/layout-sw580dp/list_section.xml b/res/layout-sw580dp/list_section.xml
deleted file mode 100644
index c684a0f..0000000
--- a/res/layout-sw580dp/list_section.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!-- Layout used for list section separators. -->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="37dip"
- android:background="@drawable/section_header_holo"
- >
- <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="@color/section_header_text_color"
- android:textSize="14sp"
- android:gravity="center"
- />
-</RelativeLayout>
diff --git a/res/layout-sw580dp/raw_contact_editor_header.xml b/res/layout-sw580dp/raw_contact_editor_header.xml
deleted file mode 100644
index a973464..0000000
--- a/res/layout-sw580dp/raw_contact_editor_header.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-
-<!-- Account info header -->
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="64dip"
- android:layout_width="match_parent"
- android:background="?android:attr/selectableItemBackground">
-
- <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"
- android:layout_alignParentRight="true"
- android:layout_below="@id/header_color_bar" />
-
- <TextView
- android:id="@+id/header_account_type"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@+id/header_icon"
- android:layout_alignTop="@id/header_icon"
- android:layout_marginTop="-4dip"
-
- android:textSize="24sp"
- android:textColor="?android:attr/textColorPrimary"
- android:singleLine="true" />
-
- <TextView
- android:id="@+id/header_account_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@+id/header_icon"
- android:layout_alignBottom="@+id/header_icon"
- android:layout_marginBottom="2dip"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorPrimary"
- android:singleLine="true" />
-
- <View
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:layout_alignParentBottom="true"
- android:background="?android:attr/listDivider"
- android:visibility="gone" />
-
-</RelativeLayout>
diff --git a/res/layout-sw580dp-w1000dp/contact_detail_header_view.xml b/res/layout-xlarge-land/contact_detail_header_view.xml
similarity index 87%
rename from res/layout-sw580dp-w1000dp/contact_detail_header_view.xml
rename to res/layout-xlarge-land/contact_detail_header_view.xml
index 82432a0..fb57202 100644
--- a/res/layout-sw580dp-w1000dp/contact_detail_header_view.xml
+++ b/res/layout-xlarge-land/contact_detail_header_view.xml
@@ -25,7 +25,7 @@
<TextView
android:id="@+id/attribution"
android:layout_width="match_parent"
- android:layout_height="@dimen/detail_header_attribution_height"
+ android:layout_height="56dip"
android:paddingRight="16dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?android:attr/textColorTertiary"
@@ -60,7 +60,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="16dip"
- android:layout_marginLeft="@dimen/detail_header_view_margin">
+ android:layout_marginLeft="16dip">
<!-- Star -->
<CheckBox
@@ -77,24 +77,33 @@
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:paddingLeft="@dimen/detail_header_view_margin"
+ android:paddingLeft="16dip"
android:orientation="vertical">
<TextView
android:id="@+id/name"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
android:textSize="@dimen/contact_name_text_size" />
<TextView
android:id="@+id/phonetic_name"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:ellipsize="end"
android:layout_marginTop="-2dip"
android:visibility="gone" />
<TextView
android:id="@+id/organization"
- style="@style/ContactDetailHeaderTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
android:layout_marginTop="-2dip"
android:visibility="gone"
android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/res/layout-xlarge-land/contact_detail_list_item.xml b/res/layout-xlarge-land/contact_detail_list_item.xml
new file mode 100644
index 0000000..9ad0e1b
--- /dev/null
+++ b/res/layout-xlarge-land/contact_detail_list_item.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="vertical"
+ android:minHeight="@dimen/detail_min_line_item_height">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_gravity="center_vertical">
+
+ <FrameLayout
+ android:layout_width="@dimen/detail_item_type_width"
+ android:layout_height="@dimen/detail_min_line_item_height"
+ android:paddingLeft="@dimen/detail_item_side_margin">
+
+ <TextView
+ android:id="@+id/kind"
+ style="@style/ContactDetailItemType" />
+
+ <TextView
+ android:id="@+id/type"
+ style="@style/ContactDetailItemType" />
+
+ </FrameLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:paddingLeft="12dip"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/data"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/footer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+ <ImageView
+ android:id="@+id/presence_icon"
+ android:layout_width="32dip"
+ android:layout_height="@dimen/detail_min_line_item_height"
+ android:layout_marginLeft="5dip"
+ android:gravity="center"
+ android:scaleType="centerInside" />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="1px"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:layout_marginLeft="14dip"
+ android:layout_marginRight="14dip"
+ android:background="?android:attr/dividerVertical" />
+
+ <FrameLayout
+ android:id="@+id/secondary_action_button_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginTop="10dip"
+ android:paddingLeft="@dimen/detail_item_icon_margin"
+ android:paddingRight="@dimen/detail_item_icon_margin"
+ android:duplicateParentState="false"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:id="@+id/secondary_action_button"
+ android:layout_width="32dip"
+ android:layout_height="match_parent"
+ android:layout_centerVertical="true"
+ android:gravity="center"
+ android:scaleType="center"
+ android:duplicateParentState="false" />
+
+ </FrameLayout>
+ </LinearLayout>
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout-xlarge/account_selector_list_item.xml b/res/layout-xlarge/account_selector_list_item.xml
new file mode 100644
index 0000000..38acfc5
--- /dev/null
+++ b/res/layout-xlarge/account_selector_list_item.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+>
+ <ImageView android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_centerVertical="true"
+ />
+
+ <TextView android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="6dip"
+ android:layout_marginTop="6dip"
+ android:layout_toRightOf="@android:id/icon"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <TextView android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@android:id/text1"
+ android:layout_alignLeft="@android:id/text1"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+</RelativeLayout>
diff --git a/res/layout-sw580dp/aggregation_suggestions.xml b/res/layout-xlarge/aggregation_suggestions.xml
similarity index 100%
rename from res/layout-sw580dp/aggregation_suggestions.xml
rename to res/layout-xlarge/aggregation_suggestions.xml
diff --git a/res/layout-sw580dp/aggregation_suggestions_item.xml b/res/layout-xlarge/aggregation_suggestions_item.xml
similarity index 95%
rename from res/layout-sw580dp/aggregation_suggestions_item.xml
rename to res/layout-xlarge/aggregation_suggestions_item.xml
index f12c608..5ea8347 100644
--- a/res/layout-sw580dp/aggregation_suggestions_item.xml
+++ b/res/layout-xlarge/aggregation_suggestions_item.xml
@@ -24,6 +24,8 @@
android:orientation="horizontal"
android:paddingLeft="5dip"
android:paddingRight="15dip"
+ android:background="?android:attr/selectableItemBackground"
+ android:focusable="true"
>
<ImageView
android:id="@+id/aggregation_suggestion_photo"
diff --git a/res/layout-sw580dp/contact_detail_fragment.xml b/res/layout-xlarge/contact_detail_fragment.xml
similarity index 76%
rename from res/layout-sw580dp/contact_detail_fragment.xml
rename to res/layout-xlarge/contact_detail_fragment.xml
index 7778736..4d6a900 100644
--- a/res/layout-sw580dp/contact_detail_fragment.xml
+++ b/res/layout-xlarge/contact_detail_fragment.xml
@@ -23,31 +23,27 @@
android:layout_height="match_parent"
android:background="@drawable/panel_content">
- <!-- Header View (including social status) -->
+ <!-- Placeholder for empty list -->
<com.android.contacts.widget.InterpolatingLayout
+ android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- >
- <com.android.contacts.detail.ContactDetailHeaderView
- android:id="@+id/contact_header_widget"
- android:layout_width="match_parent"
+ android:visibility="gone">
+ <TextView android:id="@+id/emptyText"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginBottom="28dip"
+ android:text="@string/no_contact_details"
+ android:textSize="20sp"
+ android:textColor="?android:attr/textColorSecondary"
ex:layout_wideParentWidth="800dip"
- ex:layout_wideMarginLeft="80dip"
- ex:layout_wideMarginRight="48dip"
- ex:layout_narrowParentWidth="300dip"
- ex:layout_narrowMarginLeft="5dip"
- ex:layout_narrowMarginRight="16dip"
+ ex:layout_wideMarginLeft="64dip"
+ ex:layout_narrowParentWidth="500dip"
+ ex:layout_narrowMarginLeft="42dip"
+ android:paddingTop="10dip"
+ android:lineSpacingMultiplier="0.92"
/>
</com.android.contacts.widget.InterpolatingLayout>
- <!-- Placeholder for empty list -->
- <include
- android:id="@android:id/empty"
- layout="@layout/contact_detail_empty"
- android:visibility="gone" />
-
<!-- Real list -->
<com.android.contacts.widget.InterpolatingLayout
android:layout_width="match_parent"
@@ -59,11 +55,11 @@
ex:layout_wideParentWidth="800dip"
ex:layout_wideMarginLeft="64dip"
ex:layout_widePaddingRight="48dip"
- ex:layout_narrowParentWidth="300dip"
- ex:layout_narrowMarginLeft="5dip"
+ ex:layout_narrowParentWidth="500dip"
+ ex:layout_narrowMarginLeft="32dip"
ex:layout_narrowPaddingRight="16dip"
android:cacheColorHint="#00000000"
- android:divider="@android:color/transparent"
+ android:divider="@null"
/>
</com.android.contacts.widget.InterpolatingLayout>
diff --git a/res/layout-sw580dp/contact_editor_activity.xml b/res/layout-xlarge/contact_editor_activity.xml
similarity index 100%
rename from res/layout-sw580dp/contact_editor_activity.xml
rename to res/layout-xlarge/contact_editor_activity.xml
diff --git a/res/layout-sw580dp/contact_editor_fragment.xml b/res/layout-xlarge/contact_editor_fragment.xml
similarity index 100%
rename from res/layout-sw580dp/contact_editor_fragment.xml
rename to res/layout-xlarge/contact_editor_fragment.xml
diff --git a/res/layout-sw580dp/contact_picker_content.xml b/res/layout-xlarge/contact_picker_content.xml
similarity index 100%
rename from res/layout-sw580dp/contact_picker_content.xml
rename to res/layout-xlarge/contact_picker_content.xml
diff --git a/res/layout/contact_detail_empty.xml b/res/layout-xlarge/edit_spinner.xml
similarity index 68%
copy from res/layout/contact_detail_empty.xml
copy to res/layout-xlarge/edit_spinner.xml
index e1ba04a..f1909fe 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout-xlarge/edit_spinner.xml
@@ -14,16 +14,14 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
+<!-- Spinner for a field in the contact editor. -->
-<TextView
+<Spinner
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:id="@+id/spinner"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:layout_marginLeft="@dimen/editor_field_left_padding"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:paddingLeft="5dip"
+ android:paddingTop="5dip"/>
\ No newline at end of file
diff --git a/res/layout-xlarge/event_field_editor_view.xml b/res/layout-xlarge/event_field_editor_view.xml
new file mode 100644
index 0000000..c9eef08
--- /dev/null
+++ b/res/layout-xlarge/event_field_editor_view.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Editor for a single event entry in the contact editor -->
+
+<com.android.contacts.editor.EventFieldEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/title"
+ layout="@layout/edit_field_title" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="bottom"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/date_view"
+ layout="@layout/edit_date_picker" />
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:paddingTop="15dip"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.EventFieldEditorView>
diff --git a/res/layout-sw580dp/external_raw_contact_editor_view.xml b/res/layout-xlarge/external_raw_contact_editor_view.xml
similarity index 92%
rename from res/layout-sw580dp/external_raw_contact_editor_view.xml
rename to res/layout-xlarge/external_raw_contact_editor_view.xml
index b185c8a..0304c48 100644
--- a/res/layout-sw580dp/external_raw_contact_editor_view.xml
+++ b/res/layout-xlarge/external_raw_contact_editor_view.xml
@@ -43,7 +43,7 @@
android:layout_gravity="top|left"
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="96dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginLeft="15dip">
<include
@@ -58,7 +58,7 @@
android:layout_gravity="top"
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginRight="48dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginRight="15dip"
android:orientation="vertical">
@@ -71,7 +71,7 @@
android:id="@+id/read_only_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/editor_name_text_field_left_margin"
+ android:layout_marginLeft="64dip"
android:layout_marginRight="48dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="4dip"
@@ -91,7 +91,7 @@
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="96dip"
ex:layout_wideMarginRight="96dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginLeft="15dip"
ex:layout_narrowMarginRight="15dip">
@@ -132,7 +132,7 @@
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="246dip"
ex:layout_wideMarginRight="156dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginLeft="165dip"
ex:layout_narrowMarginRight="121dip"
android:layout_width="match_parent"
diff --git a/res/layout-sw580dp/item_group_membership.xml b/res/layout-xlarge/item_group_membership.xml
similarity index 97%
rename from res/layout-sw580dp/item_group_membership.xml
rename to res/layout-xlarge/item_group_membership.xml
index 985b7ae..41d77b7 100644
--- a/res/layout-sw580dp/item_group_membership.xml
+++ b/res/layout-xlarge/item_group_membership.xml
@@ -24,7 +24,7 @@
<TextView
android:id="@+id/kind_title"
- android:layout_width="@dimen/editor_title_label_width"
+ android:layout_width="150dip"
android:layout_height="@dimen/editor_min_line_item_height"
android:gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
diff --git a/res/layout-xlarge/item_kind_section.xml b/res/layout-xlarge/item_kind_section.xml
new file mode 100644
index 0000000..f0ae1dc
--- /dev/null
+++ b/res/layout-xlarge/item_kind_section.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- the body surrounding all editors for a specific kind -->
+
+<com.android.contacts.editor.KindSectionView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/editor_field_bottom_padding"
+ android:orientation="vertical">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@drawable/divider_horizontal_light" />
+
+ <LinearLayout
+ android:id="@+id/kind_editors"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" />
+
+ <include
+ android:id="@+id/add_field_footer"
+ layout="@layout/edit_add_field" />
+
+</com.android.contacts.editor.KindSectionView>
diff --git a/res/layout-sw580dp/contact_browser.xml b/res/layout-xlarge/people_activity.xml
similarity index 100%
rename from res/layout-sw580dp/contact_browser.xml
rename to res/layout-xlarge/people_activity.xml
diff --git a/res/layout-xlarge/phonetic_name_editor_view.xml b/res/layout-xlarge/phonetic_name_editor_view.xml
new file mode 100644
index 0000000..c3fa6a3
--- /dev/null
+++ b/res/layout-xlarge/phonetic_name_editor_view.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.PhoneticNameEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical"
+ android:paddingRight="?android:attr/scrollbarSize"
+ android:layout_marginLeft="52dip"
+ android:layout_marginRight="48dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="4dip">
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.PhoneticNameEditorView>
diff --git a/res/layout-xlarge/raw_contact_editor_header.xml b/res/layout-xlarge/raw_contact_editor_header.xml
new file mode 100644
index 0000000..498998d
--- /dev/null
+++ b/res/layout-xlarge/raw_contact_editor_header.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+
+<!-- Account info header -->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="64dip"
+ android:layout_width="match_parent">
+
+ <RelativeLayout
+ android:id="@+id/account"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:id="@+id/account_icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="7dip"
+ android:layout_marginRight="7dip"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true"
+ android:layout_below="@id/header_color_bar" />
+
+ <TextView
+ android:id="@+id/account_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@+id/account_icon"
+ android:layout_alignTop="@id/account_icon"
+ android:layout_marginTop="-4dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/account_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_toLeftOf="@+id/account_icon"
+ android:layout_alignBottom="@+id/account_icon"
+ android:layout_marginBottom="2dip"
+
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true" />
+
+ <include
+ android:id="@+id/divider"
+ android:layout_alignParentBottom="true"
+ layout="@layout/edit_divider" />
+ </RelativeLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout-sw580dp/raw_contact_editor_view.xml b/res/layout-xlarge/raw_contact_editor_view.xml
similarity index 73%
rename from res/layout-sw580dp/raw_contact_editor_view.xml
rename to res/layout-xlarge/raw_contact_editor_view.xml
index eef82ec..0e3d227 100644
--- a/res/layout-sw580dp/raw_contact_editor_view.xml
+++ b/res/layout-xlarge/raw_contact_editor_view.xml
@@ -21,9 +21,14 @@
android:layout_height="wrap_content"
android:orientation="vertical">
- <include
- layout="@layout/raw_contact_editor_header"
- android:id="@+id/header" />
+ <FrameLayout
+ android:id="@+id/anchor_for_account_switcher"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <include
+ layout="@layout/raw_contact_editor_header"
+ android:id="@+id/header" />
+ </FrameLayout>
<LinearLayout
android:id="@+id/body"
@@ -43,8 +48,8 @@
android:layout_gravity="top|left"
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="96dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
- ex:layout_narrowMarginLeft="20dip">
+ ex:layout_narrowParentWidth="800dip"
+ ex:layout_narrowMarginLeft="15dip">
<include
android:id="@+id/edit_photo"
@@ -58,10 +63,8 @@
android:layout_gravity="top"
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginRight="48dip"
- ex:layout_wideMarginLeft="10dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginRight="15dip"
- ex:layout_narrowMarginLeft="5dip"
android:orientation="vertical">
<View
@@ -69,30 +72,18 @@
android:layout_height="1px"
android:background="@color/contact_detail_header_divider_color" />
- <com.android.contacts.editor.StructuredNameEditorView
+ <include
android:id="@+id/edit_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="?android:attr/scrollbarSize"
- android:layout_marginLeft="@dimen/editor_name_text_field_left_margin"
- android:layout_marginRight="48dip"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip" />
+ layout="@layout/structured_name_editor_view" />
- <com.android.contacts.editor.PhoneticNameEditorView
+ <include
android:id="@+id/edit_phonetic_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="?android:attr/scrollbarSize"
- android:layout_marginLeft="@dimen/editor_name_text_field_left_margin"
- android:layout_marginRight="48dip"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip" />
+ layout="@layout/phonetic_name_editor_view" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/editor_name_text_field_left_margin"
+ android:layout_marginLeft="52dip"
android:layout_marginRight="48dip">
<ViewStub
android:id="@+id/aggregation_suggestion_stub"
@@ -115,16 +106,16 @@
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="96dip"
ex:layout_wideMarginRight="48dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
- ex:layout_narrowMarginLeft="25dip"
- ex:layout_narrowMarginRight="10dip">
+ ex:layout_narrowParentWidth="800dip"
+ ex:layout_narrowMarginLeft="15dip"
+ ex:layout_narrowMarginRight="15dip">
<LinearLayout
android:id="@+id/sect_fields"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:paddingRight="@dimen/editor_name_text_field_right_margin" />
+ android:paddingRight="?android:attr/scrollbarSize" />
</LinearLayout>
</com.android.contacts.widget.InterpolatingLayout>
@@ -139,7 +130,7 @@
ex:layout_wideParentWidth="960dip"
ex:layout_wideMarginLeft="246dip"
ex:layout_wideMarginRight="156dip"
- ex:layout_narrowParentWidth="@dimen/editor_interpolator_narrow_width"
+ ex:layout_narrowParentWidth="800dip"
ex:layout_narrowMarginLeft="165dip"
ex:layout_narrowMarginRight="121dip"
android:layout_width="match_parent"
diff --git a/res/layout-sw580dp/search_header.xml b/res/layout-xlarge/search_header.xml
similarity index 100%
rename from res/layout-sw580dp/search_header.xml
rename to res/layout-xlarge/search_header.xml
diff --git a/res/layout-xlarge/structured_name_editor_view.xml b/res/layout-xlarge/structured_name_editor_view.xml
new file mode 100644
index 0000000..37b5536
--- /dev/null
+++ b/res/layout-xlarge/structured_name_editor_view.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.StructuredNameEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical"
+ android:paddingRight="?android:attr/scrollbarSize"
+ android:layout_marginLeft="52dip"
+ android:layout_marginRight="48dip"
+ android:layout_marginTop="6dip"
+ android:layout_marginBottom="4dip">
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.StructuredNameEditorView>
diff --git a/res/layout-xlarge/text_fields_editor_view.xml b/res/layout-xlarge/text_fields_editor_view.xml
new file mode 100644
index 0000000..8be354b
--- /dev/null
+++ b/res/layout-xlarge/text_fields_editor_view.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.TextFieldsEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/title"
+ layout="@layout/edit_field_title" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="top"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:paddingTop="15dip"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.TextFieldsEditorView>
diff --git a/res/layout-sw580dp/total_contacts.xml b/res/layout-xlarge/total_contacts.xml
similarity index 100%
rename from res/layout-sw580dp/total_contacts.xml
rename to res/layout-xlarge/total_contacts.xml
diff --git a/res/layout/account_selector_list_item.xml b/res/layout/account_selector_list_item.xml
index 38acfc5..6fe2a50 100644
--- a/res/layout/account_selector_list_item.xml
+++ b/res/layout/account_selector_list_item.xml
@@ -17,29 +17,23 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
->
- <ImageView android:id="@android:id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="6dip"
- android:layout_centerVertical="true"
- />
+ android:paddingLeft="@dimen/account_selector_horizontal_margin"
+ android:paddingRight="@dimen/account_selector_horizontal_margin"
+ android:minHeight="@dimen/account_selector_min_item_height" >
<TextView android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="6dip"
- android:layout_marginTop="6dip"
- android:layout_toRightOf="@android:id/icon"
- android:textAppearance="?android:attr/textAppearanceLarge"
+ android:layout_alignParentLeft="true"
+ android:layout_toLeftOf="@android:id/icon"
+ android:layout_centerVertical="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
/>
- <TextView android:id="@android:id/text2"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@android:id/text1"
- android:layout_alignLeft="@android:id/text1"
- android:textAppearance="?android:attr/textAppearanceSmall"
+ <ImageView android:id="@android:id/icon"
+ android:layout_width="@dimen/account_selector_icon_size"
+ android:layout_height="@dimen/account_selector_icon_size"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
/>
</RelativeLayout>
diff --git a/res/layout/aggregation_suggestions_item.xml b/res/layout/aggregation_suggestions_item.xml
index f2477cb..9ed1bf3 100644
--- a/res/layout/aggregation_suggestions_item.xml
+++ b/res/layout/aggregation_suggestions_item.xml
@@ -24,6 +24,8 @@
android:orientation="horizontal"
android:paddingLeft="5dip"
android:paddingRight="15dip"
+ android:background="?android:attr/selectableItemBackground"
+ android:focusable="true"
>
<ImageView
diff --git a/res/layout/recent_calls_list_item.xml b/res/layout/call_log_action_call.xml
similarity index 63%
copy from res/layout/recent_calls_list_item.xml
copy to res/layout/call_log_action_call.xml
index 2c519d6..747daa7 100644
--- a/res/layout/recent_calls_list_item.xml
+++ b/res/layout/call_log_action_call.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,24 +14,27 @@
limitations under the License.
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:paddingLeft="7dip"
->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <ImageView android:id="@+id/call_icon"
+ <ImageView
+ android:id="@+id/call_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="14dip"
android:paddingRight="14dip"
android:layout_alignParentRight="true"
-
android:gravity="center_vertical"
android:src="@android:drawable/sym_action_call"
- android:background="@drawable/call_background"
/>
- <include layout="@layout/recent_calls_list_item_layout"/>
+ <View android:id="@+id/divider"
+ android:layout_width="1px"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:layout_toLeftOf="@id/call_icon"
+ android:layout_marginLeft="11dip"
+ android:background="@drawable/divider_vertical_dark"
+ />
-</RelativeLayout>
+</merge>
diff --git a/res/layout/call_log_action_group.xml b/res/layout/call_log_action_group.xml
new file mode 100644
index 0000000..fa6bb79
--- /dev/null
+++ b/res/layout/call_log_action_group.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageView
+ android:id="@+id/groupIndicator"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="12dip"
+ android:paddingRight="13dip"
+ android:layout_alignParentRight="true"
+ android:gravity="center_vertical"
+ android:src="@*android:drawable/expander_ic_minimized"
+ />
+
+ <View android:id="@+id/divider"
+ android:layout_width="1px"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:layout_marginBottom="5dip"
+ android:layout_toLeftOf="@id/groupIndicator"
+ android:layout_marginLeft="11dip"
+ android:background="@drawable/divider_vertical_dark"
+ />
+
+</merge>
diff --git a/res/layout/contact_browser.xml b/res/layout/call_log_activity.xml
similarity index 69%
copy from res/layout/contact_browser.xml
copy to res/layout/call_log_activity.xml
index 0b4bb63..b391795 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/call_log_activity.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -15,7 +15,11 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+>
+ <fragment class="com.android.contacts.calllog.CallLogFragment"
+ android:id="@+id/call_log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
</FrameLayout>
diff --git a/res/layout/recent_calls.xml b/res/layout/call_log_fragment.xml
similarity index 91%
rename from res/layout/recent_calls.xml
rename to res/layout/call_log_fragment.xml
index f054b70..2a27fcd 100644
--- a/res/layout/recent_calls.xml
+++ b/res/layout/call_log_fragment.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,11 +19,11 @@
android:layout_height="match_parent"
>
<ListView android:id="@android:id/list"
- android:layout_width="match_parent"
+ android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarStyle="outsideOverlay"
/>
-
+
<TextView android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
diff --git a/res/layout/recent_calls_list_item.xml b/res/layout/call_log_list_child_item.xml
similarity index 65%
rename from res/layout/recent_calls_list_item.xml
rename to res/layout/call_log_list_child_item.xml
index 2c519d6..10e09a4 100644
--- a/res/layout/recent_calls_list_item.xml
+++ b/res/layout/call_log_list_child_item.xml
@@ -20,18 +20,7 @@
android:paddingLeft="7dip"
>
- <ImageView android:id="@+id/call_icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="14dip"
- android:paddingRight="14dip"
- android:layout_alignParentRight="true"
-
- android:gravity="center_vertical"
- android:src="@android:drawable/sym_action_call"
- android:background="@drawable/call_background"
- />
-
- <include layout="@layout/recent_calls_list_item_layout"/>
+ <include layout="@layout/call_log_action_call"/>
+ <include layout="@layout/call_log_list_item_layout"/>
</RelativeLayout>
diff --git a/res/layout/recent_calls_list_item_layout.xml b/res/layout/call_log_list_group_item.xml
similarity index 80%
copy from res/layout/recent_calls_list_item_layout.xml
copy to res/layout/call_log_list_group_item.xml
index faaa893..d1bd165 100644
--- a/res/layout/recent_calls_list_item_layout.xml
+++ b/res/layout/call_log_list_group_item.xml
@@ -14,25 +14,13 @@
limitations under the License.
-->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:paddingLeft="7dip"
+>
- <View android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_toLeftOf="@id/call_icon"
- android:layout_marginLeft="11dip"
- android:background="@drawable/divider_vertical_dark"
- />
-
- <ImageView android:id="@+id/call_type_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_marginLeft="4dip"
- />
+ <include layout="@layout/call_log_action_group"/>
<TextView android:id="@+id/date"
android:layout_width="wrap_content"
@@ -74,12 +62,26 @@
android:textAppearance="?android:attr/textAppearanceSmall"
/>
+ <TextView android:id="@+id/groupSize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@id/divider"
+ android:layout_above="@id/date"
+ android:layout_alignWithParentIfMissing="true"
+ android:layout_marginBottom="-10dip"
+
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:singleLine="true"
+ android:gravity="center_vertical"
+ />
+
<TextView android:id="@+id/line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/divider"
+ android:layout_toLeftOf="@+id/groupSize"
android:layout_above="@id/date"
android:layout_alignWithParentIfMissing="true"
android:layout_marginLeft="36dip"
@@ -90,4 +92,4 @@
android:ellipsize="marquee"
android:gravity="center_vertical"
/>
-</merge>
+</RelativeLayout>
diff --git a/res/layout/recent_calls_list_item.xml b/res/layout/call_log_list_item.xml
similarity index 65%
copy from res/layout/recent_calls_list_item.xml
copy to res/layout/call_log_list_item.xml
index 2c519d6..10e09a4 100644
--- a/res/layout/recent_calls_list_item.xml
+++ b/res/layout/call_log_list_item.xml
@@ -20,18 +20,7 @@
android:paddingLeft="7dip"
>
- <ImageView android:id="@+id/call_icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="14dip"
- android:paddingRight="14dip"
- android:layout_alignParentRight="true"
-
- android:gravity="center_vertical"
- android:src="@android:drawable/sym_action_call"
- android:background="@drawable/call_background"
- />
-
- <include layout="@layout/recent_calls_list_item_layout"/>
+ <include layout="@layout/call_log_action_call"/>
+ <include layout="@layout/call_log_list_item_layout"/>
</RelativeLayout>
diff --git a/res/layout/recent_calls_list_item_layout.xml b/res/layout/call_log_list_item_layout.xml
similarity index 89%
rename from res/layout/recent_calls_list_item_layout.xml
rename to res/layout/call_log_list_item_layout.xml
index faaa893..8096ee6 100644
--- a/res/layout/recent_calls_list_item_layout.xml
+++ b/res/layout/call_log_list_item_layout.xml
@@ -16,16 +16,6 @@
<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <View android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_toLeftOf="@id/call_icon"
- android:layout_marginLeft="11dip"
- android:background="@drawable/divider_vertical_dark"
- />
-
<ImageView android:id="@+id/call_type_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
diff --git a/res/layout/contact_detail_fragment.xml b/res/layout/contact_detail_fragment.xml
index 90a075a..70a9a28 100644
--- a/res/layout/contact_detail_fragment.xml
+++ b/res/layout/contact_detail_fragment.xml
@@ -20,16 +20,12 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <com.android.contacts.detail.ContactDetailHeaderView
- android:id="@+id/contact_header_widget"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1"
- android:background="@drawable/title_bar_shadow"
+ android:background="@color/background_primary"
+ android:divider="@null"
/>
<ScrollView android:id="@android:id/empty"
diff --git a/res/layout/contact_detail_header_view.xml b/res/layout/contact_detail_header_view.xml
index 3248920..328a5ff 100644
--- a/res/layout/contact_detail_header_view.xml
+++ b/res/layout/contact_detail_header_view.xml
@@ -14,46 +14,53 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/banner"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:background="@drawable/title_bar_medium"
- android:paddingRight="5dip">
+ android:layout_height="150dip">
<ImageView android:id="@+id/photo"
- android:layout_gravity="center_vertical"
- android:layout_marginLeft="-1dip"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:layout_marginRight="8dip"
- android:layout_width="64dip"
- android:layout_height="64dip"
- />
+ android:scaleType="centerCrop"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ />
+
+ <!-- Transparent view to overlay on the contact's photo
+ (to allow white text to appear over a white photo). -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:background="#000000"
+ android:alpha=".25"
+ />
<LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:orientation="vertical"
- android:layout_gravity="center_vertical" >
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_marginLeft="10dip"
+ android:orientation="vertical" >
<TextView android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_weight="1"
android:singleLine="true"
android:ellipsize="end"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textStyle="bold"
- android:shadowColor="#BB000000"
- android:shadowRadius="2.75"
+ android:gravity="bottom"
+ android:textSize="@dimen/detail_header_name_text_size"
+ android:textColor="@color/detail_header_view_text_color"
/>
<TextView android:id="@+id/phonetic_name"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/detail_header_view_text_color"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginTop="-2dip"
@@ -61,9 +68,10 @@
/>
<TextView android:id="@+id/organization"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/detail_header_view_text_color"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginTop="-2dip"
@@ -71,7 +79,7 @@
/>
<TextView android:id="@+id/attribution"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"
@@ -82,9 +90,10 @@
/>
<TextView android:id="@+id/status"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="@color/detail_header_view_text_color"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginTop="-2dip"
@@ -92,9 +101,8 @@
/>
<TextView android:id="@+id/status_date"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="12sp"
android:layout_marginTop="-2dip"
@@ -106,9 +114,13 @@
android:id="@+id/star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="10dip"
+ android:layout_marginRight="10dip"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentRight="true"
android:layout_gravity="center_vertical"
android:contentDescription="@string/description_star"
android:visibility="invisible"
style="?android:attr/starStyle"
/>
-</LinearLayout>
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/contact_browser.xml b/res/layout/contact_detail_header_view_list_item.xml
similarity index 71%
copy from res/layout/contact_browser.xml
copy to res/layout/contact_detail_header_view_list_item.xml
index 0b4bb63..cf149df 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/contact_detail_header_view_list_item.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,9 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
+<com.android.contacts.detail.ContactDetailHeaderView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/contact_header_widget"
android:layout_width="match_parent"
- android:layout_height="match_parent">
-</FrameLayout>
+ android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/res/layout/contact_detail_list_item.xml b/res/layout/contact_detail_list_item.xml
index fb71d87..2e4a3e5 100644
--- a/res/layout/contact_detail_list_item.xml
+++ b/res/layout/contact_detail_list_item.xml
@@ -21,114 +21,71 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:paddingLeft="@dimen/detail_item_side_margin"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
- <!-- Seperator that shows the kind -->
<LinearLayout
- android:id="@+id/kind_divider"
- android:layout_width="match_parent"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:orientation="vertical">
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@drawable/list_item_divider_holo" />
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:gravity="center_vertical">
+
<TextView
android:id="@+id/kind"
- android:gravity="center_vertical"
- android:layout_width="match_parent"
- android:layout_height="31dip"
- android:paddingLeft="8dip"
+ style="@style/ContactDetailItemType" />
+
+ <TextView
+ android:id="@+id/type"
+ style="@style/ContactDetailItemType" />
+
+ <TextView
+ android:id="@+id/data"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingBottom="5dip"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/footer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorTertiary" />
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@drawable/list_item_divider_holo" />
+ android:visibility="gone" />
</LinearLayout>
- <!-- Shorter seperating line if there was no kind-seperator -->
<ImageView
- android:id="@+id/in_kind_divider"
- android:layout_marginLeft="31dip"
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="@drawable/list_item_divider_holo" />
-
- <LinearLayout
- android:layout_width="match_parent"
+ android:id="@+id/presence_icon"
+ android:layout_width="32dip"
android:layout_height="wrap_content"
- android:minHeight="@dimen/detail_min_line_item_height"
- android:orientation="horizontal"
- android:paddingLeft="15dip"
- android:gravity="center_vertical">
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginLeft="5dip"
- android:orientation="vertical"
- android:paddingTop="5dip"
- android:paddingBottom="7dip"
- android:gravity="center_vertical">
+ android:layout_marginLeft="5dip"
+ android:gravity="center"
+ android:scaleType="centerInside" />
- <TextView
- android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium" />
+ <View
+ android:id="@+id/divider"
+ android:layout_width="1px"
+ android:layout_height="match_parent"
+ android:layout_marginTop="15dip"
+ android:layout_marginBottom="10dip"
+ android:background="?android:attr/dividerVertical" />
- <TextView
- android:id="@+id/type"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/detail_item_type_color" />
-
- <TextView
- android:id="@+id/footer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:visibility="gone" />
-
- </LinearLayout>
-
- <ImageView
- android:id="@+id/presence_icon"
- android:layout_width="32dip"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dip"
- android:gravity="center"
- android:scaleType="centerInside" />
-
- <ImageView
- android:id="@+id/action_icon"
- android:layout_width="32dip"
- android:layout_height="32dip"
- android:layout_marginLeft="16dip"
- android:gravity="center"
- android:scaleType="centerInside" />
-
- <View
- android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_marginLeft="14dip"
- android:layout_marginRight="14dip"
- android:background="?android:attr/dividerVertical" />
-
+ <FrameLayout
+ android:id="@+id/secondary_action_button_container"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginTop="5dip"
+ android:paddingLeft="@dimen/detail_item_icon_margin"
+ android:paddingRight="@dimen/detail_item_icon_margin"
+ android:duplicateParentState="false"
+ android:background="?android:attr/selectableItemBackground">
<ImageView
android:id="@+id/secondary_action_button"
android:layout_width="32dip"
android:layout_height="match_parent"
- android:layout_centerVertical="true"
- android:gravity="center"
- android:scaleType="center"
- android:background="?android:attr/selectableItemBackground" />
- </LinearLayout>
+ android:duplicateParentState="false" />
+ </FrameLayout>
</LinearLayout>
diff --git a/res/layout/contact_browser.xml b/res/layout/contact_detail_separator_list_item.xml
similarity index 71%
copy from res/layout/contact_browser.xml
copy to res/layout/contact_detail_separator_list_item.xml
index 0b4bb63..87f0597 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/contact_detail_separator_list_item.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
+<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
-</FrameLayout>
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dip"
+ android:background="@drawable/divider_horizontal_light"
+ />
\ No newline at end of file
diff --git a/res/layout/contact_editor_activity.xml b/res/layout/contact_editor_activity.xml
index 630e82c..8c13629 100644
--- a/res/layout/contact_editor_activity.xml
+++ b/res/layout/contact_editor_activity.xml
@@ -22,21 +22,4 @@
android:id="@+id/contact_editor_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="50dip"
- android:orientation="horizontal"
- android:gravity="center_horizontal">
-
- <Button
- android:id="@+id/done"
- android:layout_width="150dip"
- android:layout_height="match_parent"
- android:text="@string/menu_done" />
- <Button
- android:id="@+id/revert"
- android:layout_width="150dip"
- android:layout_height="match_parent"
- android:text="@string/menu_doNotSave" />
- </LinearLayout>
</FrameLayout>
diff --git a/res/layout/contact_editor_fragment.xml b/res/layout/contact_editor_fragment.xml
index 602f7f9..f3989e1 100644
--- a/res/layout/contact_editor_fragment.xml
+++ b/res/layout/contact_editor_fragment.xml
@@ -17,6 +17,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@color/background_primary"
>
<ScrollView
diff --git a/res/layout/dialer_activity.xml b/res/layout/dialer_activity.xml
deleted file mode 100644
index 14a6b39..0000000
--- a/res/layout/dialer_activity.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 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.
--->
-
-<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/tabhost"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TabWidget android:id="@android:id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- />
-
- <FrameLayout android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- />
- </LinearLayout>
-</TabHost>
-
diff --git a/res/layout/contact_browser.xml b/res/layout/dialpad_activity.xml
similarity index 70%
copy from res/layout/contact_browser.xml
copy to res/layout/dialpad_activity.xml
index 0b4bb63..93e9523 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/dialpad_activity.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,7 +15,11 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+>
+ <fragment class="com.android.contacts.dialpad.DialpadFragment"
+ android:id="@+id/dialpad_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
</FrameLayout>
diff --git a/res/layout/twelve_key_dialer.xml b/res/layout/dialpad_fragment.xml
similarity index 89%
rename from res/layout/twelve_key_dialer.xml
rename to res/layout/dialpad_fragment.xml
index d4c9d8f..c516bd8 100644
--- a/res/layout/twelve_key_dialer.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2006 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,11 +14,14 @@
limitations under the License.
-->
+<!-- TODO (stopship) We don't want to specify a background color here. For now we just
+keep it because otherwise the dialer needs some imagination to use (white on white) -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
+ android:background="@android:color/black"
>
<!-- Text field above the keypad where the digits are displayed.
diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml
new file mode 100644
index 0000000..7a9e7b2
--- /dev/null
+++ b/res/layout/dialtacts_activity.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <!-- Dialer --> -->
+ <fragment
+ class="com.android.contacts.dialpad.DialpadFragment"
+ android:id="@+id/dialpad_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <!-- Call Log -->
+ <fragment
+ class="com.android.contacts.calllog.CallLogFragment"
+ android:id="@+id/call_log_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <!-- Contacts -->
+ <fragment
+ android:id="@+id/contacts_fragment"
+ class="com.android.contacts.list.DefaultContactBrowseListFragment"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+
+ <!-- Favorites -->
+ <fragment
+ android:id="@+id/favorites_fragment"
+ class="com.android.contacts.list.StrequentContactListFragment"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/edit_add_field.xml b/res/layout/edit_add_field.xml
new file mode 100644
index 0000000..1c8c740
--- /dev/null
+++ b/res/layout/edit_add_field.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- Layout of "add field" row in contact editor -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="13dip"
+ android:background="?android:attr/selectableItemBackground">
+ <TextView
+ android:id="@+id/add_text"
+ android:layout_gravity="center_vertical"
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorTertiary" />
+ <ImageView
+ android:id="@+id/add_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_menu_add_field_holo_light"
+ android:paddingLeft="@dimen/editor_round_button_padding_left"
+ android:paddingRight="@dimen/editor_round_button_padding_right"
+ android:contentDescription="@string/description_plus_button" />
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/edit_date_picker.xml
similarity index 69%
copy from res/layout/contact_detail_empty.xml
copy to res/layout/edit_date_picker.xml
index e1ba04a..ca5e281 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/edit_date_picker.xml
@@ -14,16 +14,14 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
+<!-- Button to select a date in the contact editor. -->
-<TextView
+<Button
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:id="@+id/date_view"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:layout_weight="1"
+ android:layout_marginLeft="@dimen/editor_field_left_padding"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ style="@android:style/Widget.Holo.Light.Spinner" />
\ No newline at end of file
diff --git a/res/layout/edit_delete_button.xml b/res/layout/edit_delete_button.xml
new file mode 100644
index 0000000..f05b0e4
--- /dev/null
+++ b/res/layout/edit_delete_button.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- "Delete field" button in the contact editor. -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top">
+ <ImageView
+ android:id="@+id/delete_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:duplicateParentState="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:src="@drawable/ic_menu_remove_field_holo_light"
+ android:paddingLeft="@dimen/editor_round_button_padding_left"
+ android:paddingRight="@dimen/editor_round_button_padding_right"
+ android:paddingTop="@dimen/editor_round_button_padding_top"
+ android:paddingBottom="@dimen/editor_round_button_padding_bottom"
+ android:contentDescription="@string/description_minus_button" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/edit_divider.xml b/res/layout/edit_divider.xml
index eb2a49a..786bfca 100644
--- a/res/layout/edit_divider.xml
+++ b/res/layout/edit_divider.xml
@@ -16,6 +16,6 @@
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="1dip"
android:background="?android:attr/listDivider"
/>
diff --git a/res/layout/edit_expansion_view.xml b/res/layout/edit_expansion_view.xml
new file mode 100644
index 0000000..96fe8de
--- /dev/null
+++ b/res/layout/edit_expansion_view.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- "More" or "less" expansion button in the contact editor. -->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top">
+ <ImageView
+ android:id="@+id/expansion_view"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:duplicateParentState="true"
+ android:background="?android:attr/selectableItemBackground"
+ android:paddingLeft="@dimen/editor_round_button_padding_left"
+ android:paddingRight="@dimen/editor_round_button_padding_right"
+ android:paddingTop="@dimen/editor_round_button_padding_top"
+ android:paddingBottom="@dimen/editor_round_button_padding_bottom" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/edit_field_list.xml
similarity index 69%
rename from res/layout/contact_detail_empty.xml
rename to res/layout/edit_field_list.xml
index e1ba04a..ba715c7 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/edit_field_list.xml
@@ -14,16 +14,13 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
+<!-- Layout to contain a list of fields in the contact editor. -->
-<TextView
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:id="@+id/editors"
+ android:layout_width="0dip"
+ android:layout_weight="1"
android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:paddingLeft="@dimen/editor_field_left_padding"
+ android:orientation="vertical" />
\ No newline at end of file
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/edit_field_title.xml
similarity index 66%
copy from res/layout/contact_detail_empty.xml
copy to res/layout/edit_field_title.xml
index e1ba04a..4918c4d 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/edit_field_title.xml
@@ -14,16 +14,16 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
+<!-- Title of a field in the contact editor. -->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:paddingTop="@dimen/editor_field_top_padding"
+ android:paddingLeft="@dimen/editor_field_left_padding"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
\ No newline at end of file
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/edit_spinner.xml
similarity index 69%
copy from res/layout/contact_detail_empty.xml
copy to res/layout/edit_spinner.xml
index e1ba04a..9e22ee7 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/edit_spinner.xml
@@ -14,16 +14,13 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
+<!-- Spinner for a field in the contact editor. -->
-<TextView
+<Spinner
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:id="@+id/spinner"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:layout_marginLeft="@dimen/editor_field_left_padding"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:paddingLeft="5dip"/>
\ No newline at end of file
diff --git a/res/layout/event_field_editor_view.xml b/res/layout/event_field_editor_view.xml
new file mode 100644
index 0000000..6625279
--- /dev/null
+++ b/res/layout/event_field_editor_view.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Editor for a single event entry in the contact editor -->
+
+<com.android.contacts.editor.EventFieldEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/title"
+ layout="@layout/edit_field_title" />
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/date_view"
+ layout="@layout/edit_date_picker" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.EventFieldEditorView>
diff --git a/res/layout/external_raw_contact_editor_view.xml b/res/layout/external_raw_contact_editor_view.xml
index a964ce4..c524a74 100644
--- a/res/layout/external_raw_contact_editor_view.xml
+++ b/res/layout/external_raw_contact_editor_view.xml
@@ -51,7 +51,7 @@
android:background="@color/edit_divider"
/>
- <ImageView android:id="@+id/header_icon"
+ <ImageView android:id="@+id/account_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="7dip"
@@ -60,11 +60,11 @@
android:layout_below="@id/header_color_bar"
/>
- <TextView android:id="@+id/header_account_type"
+ <TextView android:id="@+id/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_toRightOf="@+id/account_icon"
+ android:layout_alignTop="@id/account_icon"
android:layout_marginTop="-4dip"
android:textSize="24sp"
@@ -72,11 +72,11 @@
android:singleLine="true"
/>
- <TextView android:id="@+id/header_account_name"
+ <TextView android:id="@+id/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_toRightOf="@+id/account_icon"
+ android:layout_alignBottom="@+id/account_icon"
android:layout_marginBottom="2dip"
android:textAppearance="?android:attr/textAppearanceSmall"
diff --git a/res/layout/group_browse_list_fragment.xml b/res/layout/group_browse_list_fragment.xml
new file mode 100644
index 0000000..50c02c8
--- /dev/null
+++ b/res/layout/group_browse_list_fragment.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <ListView
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:fastScrollEnabled="true"
+ android:scrollbarStyle="outsideOverlay"
+ android:layout_weight="1" />
+
+ <TextView
+ android:id="@+id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="@string/noGroups"
+ android:visibility="gone"/>
+
+</LinearLayout>
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
new file mode 100644
index 0000000..accbedd
--- /dev/null
+++ b/res/layout/group_browse_list_item.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:scaleType="center"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="10dip"
+ android:layout_gravity="center_vertical" />
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip">
+
+ <TextView
+ android:id="@+id/label"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:ellipsize="end"
+ android:singleLine="true" />
+
+ <TextView
+ android:id="@+id/account"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:gravity="center_vertical"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textStyle="italic" />
+
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/contact_browser.xml b/res/layout/group_browser_activity.xml
similarity index 73%
rename from res/layout/contact_browser.xml
rename to res/layout/group_browser_activity.xml
index 0b4bb63..f7187d9 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/group_browser_activity.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,7 +15,14 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+ <fragment
+ android:id="@+id/list_fragment"
+ class="com.android.contacts.group.GroupBrowseListFragment"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ />
+
</FrameLayout>
diff --git a/res/layout/contact_browser.xml b/res/layout/group_detail_activity.xml
similarity index 73%
copy from res/layout/contact_browser.xml
copy to res/layout/group_detail_activity.xml
index 0b4bb63..707a65c 100644
--- a/res/layout/contact_browser.xml
+++ b/res/layout/group_detail_activity.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,7 +15,13 @@
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
+
+ <fragment
+ class="com.android.contacts.group.GroupDetailFragment"
+ android:id="@+id/group_detail_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
</FrameLayout>
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/group_detail_fragment.xml
similarity index 63%
copy from res/layout/contact_detail_empty.xml
copy to res/layout/group_detail_fragment.xml
index e1ba04a..70d67b6 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/group_detail_fragment.xml
@@ -14,16 +14,16 @@
limitations under the License.
-->
-<!-- Placeholder for empty details for a contact -->
-
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/group_detail"
+ android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:layout_height="match_parent">
+
+ <ListView
+ android:id="@+id/member_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:scrollbarStyle="outsideOverlay"/>
+
+</LinearLayout>
diff --git a/res/layout/item_group_membership.xml b/res/layout/item_group_membership.xml
index 65730d4..cdf4e8a 100644
--- a/res/layout/item_group_membership.xml
+++ b/res/layout/item_group_membership.xml
@@ -21,11 +21,6 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="vertical">
- <View
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="?android:attr/listDivider" />
-
<LinearLayout
android:id="@+id/kind_header"
android:layout_width="match_parent"
diff --git a/res/layout/item_kind_section.xml b/res/layout/item_kind_section.xml
index fdb55c9..6c6f960 100644
--- a/res/layout/item_kind_section.xml
+++ b/res/layout/item_kind_section.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.
@@ -20,59 +20,22 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingBottom="@dimen/editor_field_bottom_padding"
android:orientation="vertical">
<View
android:layout_width="match_parent"
- android:layout_height="1px"
- android:background="?android:attr/listDivider" />
-
- <LinearLayout
- android:id="@+id/kind_header"
- android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginLeft="14dip"
- android:layout_marginTop="2dip"
- android:layout_marginBottom="2dip"
- android:layout_marginRight="?android:attr/scrollbarSize"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- android:focusable="true"
- android:clickable="true">
-
- <TextView
- android:id="@+id/kind_title"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/kind_title"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
-
- <ImageButton
- android:id="@+id/kind_plus"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:duplicateParentState="true"
- android:background="?android:attr/selectableItemBackground"
- android:src="@drawable/ic_menu_add_field_holo_light"
- android:paddingLeft="@dimen/editor_round_button_padding_left"
- android:paddingRight="@dimen/editor_round_button_padding_right"
- android:paddingTop="@dimen/editor_round_button_padding_top"
- android:paddingBottom="@dimen/editor_round_button_padding_bottom"
- android:contentDescription="@string/description_plus_button" />
-
- </LinearLayout>
+ android:background="@drawable/divider_horizontal_light" />
<LinearLayout
android:id="@+id/kind_editors"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingBottom="6dip"
android:orientation="vertical" />
-</com.android.contacts.editor.KindSectionView>
+ <include
+ android:id="@+id/add_field_footer"
+ layout="@layout/edit_add_field" />
+
+</com.android.contacts.editor.KindSectionView>
\ No newline at end of file
diff --git a/res/layout/item_photo_editor.xml b/res/layout/item_photo_editor.xml
index 642908e..3590963 100644
--- a/res/layout/item_photo_editor.xml
+++ b/res/layout/item_photo_editor.xml
@@ -27,7 +27,7 @@
android:src="@drawable/ic_contact_picture"
android:cropToPadding="true"
android:scaleType="centerCrop"
- android:gravity="center"
+ android:gravity="left"
/>
<View
android:id="@+id/frame"
diff --git a/res/layout/list_section.xml b/res/layout/list_section.xml
index e920673..5265f88 100644
--- a/res/layout/list_section.xml
+++ b/res/layout/list_section.xml
@@ -18,8 +18,7 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="25dip"
- android:background="@drawable/section_header"
+ android:layout_height="@dimen/list_section_height"
>
<TextView
android:id="@+id/header_text"
diff --git a/res/layout/people_activity.xml b/res/layout/people_activity.xml
new file mode 100644
index 0000000..8affd46
--- /dev/null
+++ b/res/layout/people_activity.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/list_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:id="@+id/main_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <fragment
+ android:id="@+id/list_fragment"
+ class="com.android.contacts.list.DefaultContactBrowseListFragment"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ />
+ </FrameLayout>
+ <FrameLayout
+ android:id="@+id/contacts_unavailable_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone">
+ <FrameLayout
+ android:id="@+id/contacts_unavailable_container"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent" />
+ </FrameLayout>
+</FrameLayout>
diff --git a/res/layout/phonetic_name_editor_view.xml b/res/layout/phonetic_name_editor_view.xml
new file mode 100644
index 0000000..832ca2c
--- /dev/null
+++ b/res/layout/phonetic_name_editor_view.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.PhoneticNameEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="@dimen/editor_field_bottom_padding"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.PhoneticNameEditorView>
diff --git a/res/layout/quickcontact.xml b/res/layout/quickcontact.xml
index a74424c..e2b291c 100644
--- a/res/layout/quickcontact.xml
+++ b/res/layout/quickcontact.xml
@@ -1,3 +1,4 @@
+<?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");
@@ -12,13 +13,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<view
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.contacts.quickcontact.QuickContactRootLayout"
- android:id="@+id/root"
- android:layout_width="match_parent"
+ android:id="@android:id/content"
+ android:layout_width="@dimen/quick_contact_width"
android:layout_height="wrap_content"
+ android:visibility="invisible"
android:orientation="vertical">
<FrameLayout
@@ -133,4 +133,4 @@
android:text="@string/quickcontact_clear_defaults_button" />
</LinearLayout>
</FrameLayout>
-</view>
+</LinearLayout>
diff --git a/res/layout/contact_detail_empty.xml b/res/layout/quickcontact_activity.xml
similarity index 68%
copy from res/layout/contact_detail_empty.xml
copy to res/layout/quickcontact_activity.xml
index e1ba04a..aced4a8 100644
--- a/res/layout/contact_detail_empty.xml
+++ b/res/layout/quickcontact_activity.xml
@@ -13,17 +13,16 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<!-- Placeholder for empty details for a contact -->
-
-<TextView
+<view
xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.contacts.quickcontact.FloatingChildLayout"
+ android:id="@+id/floating_layout"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/no_contact_details"
- android:textSize="20sp"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_marginLeft="15dip"
- android:paddingTop="10dip"
- android:lineSpacingMultiplier="0.92"
-/>
\ No newline at end of file
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:descendantFocusability="afterDescendants">
+
+ <include layout="@layout/quickcontact" />
+
+</view>
diff --git a/res/layout/quickcontact_default_item.xml b/res/layout/quickcontact_default_item.xml
index 25b6910..3a918f0 100755
--- a/res/layout/quickcontact_default_item.xml
+++ b/res/layout/quickcontact_default_item.xml
@@ -28,13 +28,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
- android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+ android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dip"
- android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+ android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
diff --git a/res/layout/quickcontact_resolve_item.xml b/res/layout/quickcontact_resolve_item.xml
index 55de80e..2805722 100755
--- a/res/layout/quickcontact_resolve_item.xml
+++ b/res/layout/quickcontact_resolve_item.xml
@@ -28,13 +28,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
- android:textAppearance="?android:attr/textAppearanceMediumInverse" />
+ android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@android:id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dip"
- android:textAppearance="?android:attr/textAppearanceSmallInverse" />
+ android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
diff --git a/res/layout/raw_contact_editor_view.xml b/res/layout/raw_contact_editor_view.xml
index ac30a6b..5aa1e95 100644
--- a/res/layout/raw_contact_editor_view.xml
+++ b/res/layout/raw_contact_editor_view.xml
@@ -21,96 +21,80 @@
android:orientation="vertical"
>
- <!-- Account info header -->
- <RelativeLayout android:id="@+id/header"
- android:layout_height="64dip"
- android:layout_width="match_parent"
- android:background="@android:drawable/list_selector_background"
- >
-
- <ImageView android:id="@+id/header_color_bar"
- android:layout_width="match_parent"
- android:layout_height="4dip"
- android:layout_marginBottom="5dip"
- android:background="@color/edit_divider"
- />
-
- <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"
- android:layout_below="@id/header_color_bar"
- />
-
- <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="24sp"
- android:textColor="?android:attr/textColorPrimary"
- android:singleLine="true"
- />
-
- <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"
- android:singleLine="true"
- />
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1px"
- android:layout_alignParentBottom="true"
-
- android:background="?android:attr/listDivider"
- />
- </RelativeLayout>
-
<LinearLayout
android:id="@+id/body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
- <FrameLayout
- android:id="@+id/stub_photo"
- android:layout_width="match_parent"
+ <LinearLayout
+ android:id="@+id/anchor_for_account_switcher"
android:layout_height="wrap_content"
- android:paddingLeft="12dip"
- android:paddingTop="10dip">
+ android:layout_width="match_parent"
+ android:layout_marginRight="4dip"
+ android:background="@android:drawable/list_selector_background"
+ android:orientation="horizontal"
+ android:gravity="left|center_vertical">
- <include
- android:id="@+id/edit_photo"
- layout="@layout/item_photo_editor" />
+ <FrameLayout
+ android:id="@+id/stub_photo"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
- </FrameLayout>
+ <include
+ android:id="@+id/edit_photo"
+ layout="@layout/item_photo_editor" />
- <com.android.contacts.editor.StructuredNameEditorView
+ </FrameLayout>
+
+ <LinearLayout
+ android:id="@+id/account"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:paddingLeft="@dimen/account_selector_horizontal_margin"
+ android:paddingRight="@dimen/account_selector_horizontal_margin"
+ android:background="@color/account_selection_background"
+ android:orientation="vertical"
+ android:gravity="left|center_vertical">
+ <TextView
+ android:id="@+id/account_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ android:singleLine="true" />
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/account_name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorPrimaryInverse"
+ android:singleLine="true" />
+
+ <ImageView
+ android:id="@+id/account_icon"
+ android:layout_width="@dimen/account_selector_icon_size"
+ android:layout_height="@dimen/account_selector_icon_size" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+
+
+ <include
android:id="@+id/edit_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="?android:attr/scrollbarSize"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip" />
+ layout="@layout/structured_name_editor_view" />
- <com.android.contacts.editor.PhoneticNameEditorView
+ <include
android:id="@+id/edit_phonetic_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="?android:attr/scrollbarSize"
- android:layout_marginTop="6dip"
- android:layout_marginBottom="4dip" />
+ layout="@layout/phonetic_name_editor_view" />
<ViewStub android:id="@+id/aggregation_suggestion_stub"
android:inflatedId="@+id/aggregation_suggestion"
diff --git a/res/layout/recent_calls_list_child_item.xml b/res/layout/recent_calls_list_child_item.xml
deleted file mode 100644
index 527e259..0000000
--- a/res/layout/recent_calls_list_child_item.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:paddingLeft="7dip"
- android:background="@drawable/list_item_background_secondary"
->
-
- <ImageView android:id="@+id/call_icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="14dip"
- android:paddingRight="14dip"
- android:layout_alignParentRight="true"
-
- android:gravity="center_vertical"
- android:src="@android:drawable/sym_action_call"
- android:background="@drawable/call_background_secondary"
- />
-
- <include layout="@layout/recent_calls_list_item_layout"/>
-
-</RelativeLayout>
diff --git a/res/layout/recent_calls_list_group_item.xml b/res/layout/recent_calls_list_group_item.xml
deleted file mode 100644
index 79423fa..0000000
--- a/res/layout/recent_calls_list_group_item.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:paddingLeft="7dip"
->
-
- <ImageView android:id="@+id/call_icon"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="14dip"
- android:paddingRight="14dip"
- android:layout_alignParentRight="true"
-
- android:gravity="center_vertical"
- android:src="@android:drawable/sym_action_call"
- android:background="@drawable/call_background"
- />
-
- <View android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="match_parent"
- android:layout_marginTop="5dip"
- android:layout_marginBottom="5dip"
- android:layout_toLeftOf="@id/call_icon"
- android:layout_marginLeft="11dip"
- android:background="@drawable/divider_vertical_dark"
- />
-
- <TextView android:id="@+id/date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toLeftOf="@id/divider"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="8dip"
- android:layout_marginLeft="10dip"
-
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
- />
-
- <TextView android:id="@+id/label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- android:layout_marginLeft="36dip"
- android:layout_marginRight="5dip"
- android:layout_alignBaseline="@id/date"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- />
-
- <TextView android:id="@+id/number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_toRightOf="@id/label"
- android:layout_toLeftOf="@id/date"
- android:layout_alignBaseline="@id/label"
- android:layout_alignWithParentIfMissing="true"
-
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
-
- <TextView android:id="@+id/groupSize"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/divider"
- android:layout_above="@id/date"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginBottom="-10dip"
-
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:singleLine="true"
- android:gravity="center_vertical"
- />
-
- <TextView android:id="@+id/line1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@+id/groupSize"
- android:layout_above="@id/date"
- android:layout_alignWithParentIfMissing="true"
- android:layout_marginLeft="36dip"
- android:layout_marginBottom="-10dip"
-
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:gravity="center_vertical"
- />
-
- <ImageView
- android:id="@+id/groupIndicator"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:src="@*android:drawable/expander_ic_minimized"
- android:gravity="center_vertical"
- />
-</RelativeLayout>
diff --git a/res/layout/structured_name_editor_view.xml b/res/layout/structured_name_editor_view.xml
new file mode 100644
index 0000000..83efa6f
--- /dev/null
+++ b/res/layout/structured_name_editor_view.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.StructuredNameEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/divider"
+ layout="@layout/edit_divider" />
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.StructuredNameEditorView>
diff --git a/res/layout/text_fields_editor_view.xml b/res/layout/text_fields_editor_view.xml
new file mode 100644
index 0000000..d33e804
--- /dev/null
+++ b/res/layout/text_fields_editor_view.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<com.android.contacts.editor.TextFieldsEditorView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/title"
+ layout="@layout/edit_field_title" />
+
+ <include
+ android:id="@+id/spinner"
+ layout="@layout/edit_spinner"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:focusable="true"
+ android:clickable="true">
+
+ <include
+ android:id="@+id/editors"
+ layout="@layout/edit_field_list" />
+
+ <include
+ android:id="@+id/expansion_view_container"
+ layout="@layout/edit_expansion_view"
+ android:visibility="gone" />
+
+ <include
+ android:id="@+id/delete_button_container"
+ layout="@layout/edit_delete_button"
+ android:visibility="gone" />
+
+ </LinearLayout>
+
+</com.android.contacts.editor.TextFieldsEditorView>
diff --git a/res/menu-sw580dp-w720dp/actions.xml b/res/menu-sw580dp-w720dp/actions.xml
deleted file mode 100644
index 86b77b6..0000000
--- a/res/menu-sw580dp-w720dp/actions.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_add"
- android:showAsAction="always" />
-
- <item
- android:id="@+id/menu_settings"
- android:icon="@drawable/ic_menu_settings_holo_light"
- android:title="@string/menu_settings" />
-
- <item
- android:id="@+id/menu_accounts"
- android:icon="@drawable/ic_menu_accounts_holo_light"
- android:title="@string/menu_accounts" />
-
- <item
- android:id="@+id/menu_import_export"
- android:icon="@drawable/ic_menu_import_export_holo_light"
- android:title="@string/menu_import_export" />
-
- <item
- android:id="@+id/menu_rename_group"
- android:icon="@drawable/ic_menu_settings_holo_light"
- android:title="@string/menu_renameGroup" />
-
- <item
- android:id="@+id/menu_delete_group"
- android:icon="@drawable/ic_menu_trash_holo_light"
- android:title="@string/menu_deleteGroup" />
-</menu>
diff --git a/res/menu-sw580dp-w720dp/view.xml b/res/menu-sw580dp-w720dp/view.xml
deleted file mode 100644
index 5be1b6b..0000000
--- a/res/menu-sw580dp-w720dp/view.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_edit"
- android:icon="@drawable/ic_menu_compose_holo_light"
- android:title="@string/menu_editContact"
- android:alphabeticShortcut="e"
- android:showAsAction="always" />
-
- <item
- android:id="@+id/menu_share"
- android:icon="@drawable/ic_menu_share_holo_light"
- android:title="@string/menu_share"
- android:alphabeticShortcut="s" />
-
- <item
- android:id="@+id/menu_options"
- android:icon="@drawable/ic_menu_mark"
- android:title="@string/menu_contactOptions" />
-
- <item
- android:id="@+id/menu_delete"
- android:icon="@drawable/ic_menu_trash_holo_light"
- android:title="@string/menu_deleteContact" />
-</menu>
diff --git a/res/menu-sw580dp/actions.xml b/res/menu-sw580dp/actions.xml
deleted file mode 100644
index de5110f..0000000
--- a/res/menu-sw580dp/actions.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_new_contact"
- android:icon="@drawable/ic_menu_add_contact_holo_light"
- android:title="@string/menu_new_contact_action_bar" />
-
- <item
- android:id="@+id/menu_settings"
- android:icon="@drawable/ic_menu_settings_holo_light"
- android:title="@string/menu_settings" />
-
- <item
- android:id="@+id/menu_accounts"
- android:icon="@drawable/ic_menu_accounts_holo_light"
- android:title="@string/menu_accounts" />
-
- <item
- android:id="@+id/menu_import_export"
- android:icon="@drawable/ic_menu_import_export_holo_light"
- android:title="@string/menu_import_export" />
-
- <item
- android:id="@+id/menu_rename_group"
- android:icon="@drawable/ic_menu_settings_holo_light"
- android:title="@string/menu_renameGroup" />
-
- <item
- android:id="@+id/menu_delete_group"
- android:icon="@drawable/ic_menu_trash_holo_light"
- android:title="@string/menu_deleteGroup" />
-</menu>
diff --git a/res/menu-sw580dp/view.xml b/res/menu-sw580dp/view.xml
deleted file mode 100644
index 7cf17d6..0000000
--- a/res/menu-sw580dp/view.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/menu_edit"
- android:icon="@drawable/ic_menu_compose_holo_light"
- android:title="@string/menu_editContact"
- android:alphabeticShortcut="e" />
-
- <item
- android:id="@+id/menu_share"
- android:icon="@drawable/ic_menu_share_holo_light"
- android:title="@string/menu_share"
- android:alphabeticShortcut="s" />
-
- <item
- android:id="@+id/menu_options"
- android:icon="@drawable/ic_menu_mark"
- android:title="@string/menu_contactOptions" />
-
- <item
- android:id="@+id/menu_delete"
- android:icon="@drawable/ic_menu_trash_holo_light"
- android:title="@string/menu_deleteContact" />
-</menu>
diff --git a/res/menu/list.xml b/res/menu/list.xml
index 2b3f453..56d92f8 100644
--- a/res/menu/list.xml
+++ b/res/menu/list.xml
@@ -27,9 +27,9 @@
android:alphabeticShortcut="n" />
<item
- android:id="@+id/menu_display_groups"
- android:icon="@*android:drawable/ic_menu_allfriends"
- android:title="@string/menu_displayGroup" />
+ android:id="@+id/menu_settings"
+ android:icon="@drawable/ic_menu_settings_holo_light"
+ android:title="@string/menu_settings" />
<item
android:id="@+id/menu_accounts"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
new file mode 100644
index 0000000..07f2b7c
--- /dev/null
+++ b/res/values-af/strings.xml
@@ -0,0 +1,680 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for sharedUserLabel (7965035505237135241) -->
+ <skip />
+ <!-- no translation found for contactsList (8661624236494819731) -->
+ <skip />
+ <string name="launcherDialer" msgid="8636288196618486553">"Foon"</string>
+ <!-- no translation found for shortcutContact (749243779392912958) -->
+ <skip />
+ <string name="shortcutDialContact" msgid="746622101599186779">"Direk skakel"</string>
+ <string name="shortcutMessageContact" msgid="2460337253595976198">"Direkte boodskap"</string>
+ <string name="shortcutActivityTitle" msgid="6642877210643565436">"Kies \'n kontakkortpad"</string>
+ <string name="callShortcutActivityTitle" msgid="6065749861423648991">"Kies \'n nommer om te bel"</string>
+ <string name="messageShortcutActivityTitle" msgid="3084542316620335911">"Kies \'n nommer om te stuur"</string>
+ <!-- no translation found for contactPickerActivityTitle (6886592363525235031) -->
+ <skip />
+ <!-- no translation found for starredList (4817256136413959463) -->
+ <skip />
+ <!-- no translation found for frequentList (7154768136473953056) -->
+ <skip />
+ <!-- no translation found for strequentList (5640192862059373511) -->
+ <skip />
+ <!-- no translation found for viewContactTitle (7989394521836644384) -->
+ <skip />
+ <!-- no translation found for viewContactDesription (214186610887547860) -->
+ <skip />
+ <!-- no translation found for editContactDescription (2947202828256214947) -->
+ <skip />
+ <!-- no translation found for insertContactDescription (4709878105452681987) -->
+ <skip />
+ <!-- no translation found for searchHint (8482945356247760701) -->
+ <skip />
+ <string name="menu_search" msgid="9147752853603483719">"Soek"</string>
+ <!-- no translation found for menu_newContact (1209922412763274638) -->
+ <skip />
+ <!-- no translation found for menu_viewContact (2795575601596468581) -->
+ <skip />
+ <string name="menu_callNumber" msgid="5142851348489387516">"Bel <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for menu_addStar (2908478235715404876) -->
+ <skip />
+ <!-- no translation found for menu_removeStar (5844227078364227030) -->
+ <skip />
+ <!-- no translation found for menu_editContact (3452858480713561396) -->
+ <skip />
+ <!-- no translation found for menu_deleteContact (1916555454274101750) -->
+ <skip />
+ <string name="menu_call" msgid="3992595586042260618">"Bel kontak"</string>
+ <string name="menu_sendSMS" msgid="5535886767547006515">"Teks - kontak"</string>
+ <string name="menu_makeDefaultEmail" msgid="2599044610375789994">"Stel as verstek e-posprogram"</string>
+ <string name="menu_splitAggregate" msgid="8368636463748691868">"Skei"</string>
+ <!-- no translation found for menu_renameGroup (2798886925154156075) -->
+ <skip />
+ <!-- no translation found for menu_deleteGroup (644571524292675446) -->
+ <skip />
+ <!-- no translation found for menu_new_contact_action_bar (8887818026717394343) -->
+ <skip />
+ <string name="splitConfirmation_title" msgid="6716467920283502570">"Skei kontak"</string>
+ <string name="splitConfirmation" msgid="1150797297503944823">"Is jy seker jy wil hierdie enkele kontak in meerdere kontakte opdeel: een vir elke stel kontakinligting wat daarby saamgevoeg is?"</string>
+ <string name="menu_joinAggregate" msgid="5027981918265667970">"Voeg saam"</string>
+ <string name="titleJoinContactDataWith" msgid="7684875775798635354">"Voeg kontakte saam"</string>
+ <string name="blurbJoinContactDataWith" msgid="995870557595050304">"Kies die kontak wat jy wil saamvoeg met <xliff:g id="NAME">%s</xliff:g>."</string>
+ <string name="showAllContactsJoinItem" msgid="2189695051430392383">"Wys alle kontakte"</string>
+ <string name="separatorJoinAggregateSuggestions" msgid="2831414448851313345">"Voorgestelde kontakte"</string>
+ <string name="separatorJoinAggregateAll" msgid="7939932265026181043">"Alle kontakte"</string>
+ <string name="contactsJoinedMessage" msgid="7208148163607047389">"Kontakte saamgevoeg"</string>
+ <string name="menu_contactOptions" msgid="1957061455705020617">"Opsies"</string>
+ <string name="contactOptionsTitle" msgid="8259347644090700915">"Opsies"</string>
+ <!-- no translation found for deleteConfirmation_title (6394309508930335204) -->
+ <skip />
+ <string name="readOnlyContactWarning" msgid="1390849295342594265">"Jy kan nie kontakte uit leesalleen-rekeninge uitvee nie, maar jy kan hulle wel in jou kontaklyste versteek."</string>
+ <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"Hierdie kontak bevat inligting uit meerdere rekeninge. Inligting uit leesalleen-rekeninge sal in jou kontaklyste versteek word, nie verwyder word nie."</string>
+ <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"As jy hierdie kontak uitvee, sal dit inligting uit meerdere rekeninge uitvee."</string>
+ <!-- no translation found for deleteConfirmation (811706994761610640) -->
+ <skip />
+ <string name="menu_done" msgid="796017761764190697">"Klaar"</string>
+ <!-- outdated translation 2174577548513895144 --> <string name="menu_doNotSave" msgid="58593876893538465">"Laai terug"</string>
+ <!-- no translation found for editContact_title_edit (7678695190666836093) -->
+ <skip />
+ <!-- no translation found for editContact_title_insert (9125600232291405757) -->
+ <skip />
+ <string name="label_phonetic_name" msgid="2288082649573927286">"Foneties"</string>
+ <!-- no translation found for label_notes (8337354953278341042) -->
+ <skip />
+ <!-- no translation found for label_sip_address (124073911714324974) -->
+ <skip />
+ <!-- no translation found for label_ringtone (8833166825330686244) -->
+ <skip />
+ <string name="ghostData_phonetic_name" msgid="7852749081984070902">"Fonetiese naam"</string>
+ <!-- no translation found for ghostData_company (5414421120553765775) -->
+ <skip />
+ <!-- no translation found for ghostData_title (7496735200318496110) -->
+ <skip />
+ <!-- no translation found for invalidContactMessage (5816991830260044593) -->
+ <skip />
+ <!-- no translation found for pickerNewContactHeader (7750705279843568147) -->
+ <skip />
+ <!-- no translation found for phoneLabelsGroup (6468091477851199285) -->
+ <skip />
+ <!-- no translation found for emailLabelsGroup (8389931313045344406) -->
+ <skip />
+ <!-- no translation found for imLabelsGroup (3898238486262614027) -->
+ <skip />
+ <!-- no translation found for postalLabelsGroup (3487738141112589324) -->
+ <skip />
+ <string-array name="otherLabels">
+ <item msgid="8287841928119937597">"Organisasie"</item>
+ <item msgid="7196592230748086755">"Let wel"</item>
+ </string-array>
+ <!-- no translation found for photoPickerNotFoundText (6247290728908599701) -->
+ <skip />
+ <!-- no translation found for photoPickerNotFoundText (431331662154342581) -->
+ <skip />
+ <!-- no translation found for attach_photo_dialog_title (5599827035558557169) -->
+ <skip />
+ <string name="customLabelPickerTitle" msgid="1081475101983255212">"Gepasmaakte etiketnaam"</string>
+ <string name="menu_displayGroup" msgid="5655505437727616553">"Vertoonopsies"</string>
+ <string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"Stuur oproepe direk na stemboodskap"</string>
+ <!-- no translation found for default_ringtone (9099988849649827972) -->
+ <skip />
+ <!-- no translation found for removePhoto (4898105274130284565) -->
+ <skip />
+ <!-- no translation found for noContacts (8579310973261953559) -->
+ <skip />
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
+ <string name="noMatchingContacts" msgid="4266283206853990471">"Geen passende kontakte gevind nie."</string>
+ <!-- no translation found for noContactsWithPhoneNumbers (1605457050218824269) -->
+ <skip />
+ <string name="showFilterPhones" msgid="4184858075465653970">"Net kontakte met fone"</string>
+ <string name="showFilterPhonesDescrip" msgid="6644443248815191067">"Wys net kontakte wat foonnommers het"</string>
+ <string name="headerContactGroups" msgid="2426134991932503843">"Kies kontakte om te wys"</string>
+ <plurals name="groupDescrip">
+ <item quantity="other" msgid="3507881585720628389">"<xliff:g id="COUNT">%0$d</xliff:g> kontakte"</item>
+ </plurals>
+ <plurals name="groupDescripPhones">
+ <item quantity="other" msgid="3816047547470490208">"<xliff:g id="COUNT_0">%1$d</xliff:g> kontakte, <xliff:g id="COUNTWITHPHONES">%2$d</xliff:g> met fone"</item>
+ </plurals>
+ <string name="savingContact" msgid="4075751076741924939">"Stoor tans kontak..."</string>
+ <string name="savingDisplayGroups" msgid="2133152192716475939">"Stoor tans vertoonopsies..."</string>
+ <!-- no translation found for contactSavedToast (7152589189385441091) -->
+ <skip />
+ <string name="contactSavedErrorToast" msgid="9189098776225004666">"Fout, kan nie kontakwysigings stoor nie."</string>
+ <!-- no translation found for listTotalPhoneContacts:other (3299954047880968205) -->
+ <!-- outdated translation 2756295259674938869 --> <string name="listTotalPhoneContactsZero" msgid="6968813857632984319">"Geen sigbare kontakte met foonnommers nie"</string>
+ <!-- no translation found for listTotalAllContacts:other (3578469907265375314) -->
+ <!-- outdated translation 6811347506748072822 --> <string name="listTotalAllContactsZero" msgid="1889349925514589304">"Geen sigbare kontakte nie"</string>
+ <!-- no translation found for listTotalAllContactsZeroCustom (4058252141420128998) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroStarred (5391630590684099117) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroGroup (5448979458248027615) -->
+ <skip />
+ <!-- no translation found for listFoundAllContacts:other (3852668542926965042) -->
+ <!-- no translation found for foundTooManyContacts (2548148047461758967) -->
+ <skip />
+ <!-- outdated translation 5554368784319460828 --> <string name="listFoundAllContactsZero" msgid="777952841930508289">"Kontak nie gevind nie"</string>
+ <!-- no translation found for searchFoundContacts:one (4826918429708286628) -->
+ <!-- no translation found for searchFoundContacts:other (7988132539476575389) -->
+ <!-- no translation found for contactsIconLabel (7666609097606552806) -->
+ <skip />
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
+ <!-- no translation found for contactsFavoritesLabel (8417039765586853670) -->
+ <skip />
+ <string name="dialerIconLabel" msgid="6500826552823403796">"Foon"</string>
+ <!-- no translation found for recentCallsIconLabel (1419116422359067949) -->
+ <skip />
+ <string name="liveFolderAll" msgid="4789010460767506206">"Alle kontakte"</string>
+ <string name="liveFolderFavorites" msgid="3100957542927222282">"Gesterde kontakte"</string>
+ <string name="liveFolderPhone" msgid="3739376066610926780">"Kontakte met foonnommers"</string>
+ <string name="menu_sendTextMessage" msgid="6937343460284499306">"Stuur teksboodskap"</string>
+ <string name="recentCalls_callNumber" msgid="1756372533999226126">"Bel <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for recentCalls_editNumberBeforeCall (7756171675833267857) -->
+ <skip />
+ <!-- no translation found for recentCalls_addToContact (1429899535546487008) -->
+ <skip />
+ <!-- no translation found for recentCalls_removeFromRecentList (401662244636511330) -->
+ <skip />
+ <!-- no translation found for recentCalls_deleteAll (6352364392762163704) -->
+ <skip />
+ <!-- no translation found for recentCalls_empty (247053222448663107) -->
+ <skip />
+ <!-- no translation found for clearCallLogConfirmation_title (718072843006222703) -->
+ <skip />
+ <!-- no translation found for clearCallLogConfirmation (7625927669136267636) -->
+ <skip />
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
+ <!-- no translation found for imei (3045126336951684285) -->
+ <skip />
+ <string name="meid" msgid="6210568493746275750">"MEID"</string>
+ <!-- no translation found for voicemail (3851469869202611441) -->
+ <skip />
+ <!-- no translation found for unknown (740067747858270469) -->
+ <skip />
+ <!-- no translation found for private_num (6374339738119166953) -->
+ <skip />
+ <string name="payphone" msgid="4864313342828942922">"Betaalfoon"</string>
+ <!-- no translation found for dialerKeyboardHintText (5401660096579787344) -->
+ <skip />
+ <string name="dialerDialpadHintText" msgid="5824490365898349041">"Skakel om \'n oproep by te voeg"</string>
+ <!-- no translation found for simContacts_emptyLoading (6700035985448642408) -->
+ <skip />
+ <!-- no translation found for simContacts_title (27341688347689769) -->
+ <skip />
+ <!-- no translation found for noContactsHelpTextWithSyncForCreateShortcut (801504710275614594) -->
+ <skip />
+ <!-- no translation found for noContactsHelpTextForCreateShortcut (3081286388667108335) -->
+ <skip />
+ <!-- outdated translation 6788487368878712350 --> <string name="noContactsHelpText" product="tablet" msgid="6450346791169710787">"Jy het nie enige kontakte om te wys nie."\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg of op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Voer in/uit"</b></font>\n</li></string>
+ <!-- outdated translation 6788487368878712350 --> <string name="noContactsHelpText" product="default" msgid="7633826236417884130">"Jy het nie enige kontakte om te wys nie."\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg of op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Voer in/uit"</b></font>\n</li></string>
+ <!-- outdated translation 3734101165712848179 --> <string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"Jy het nie enige kontakte om te wys nie. (As jy sopas \'n rekening bygevoeg het, kan dit \'n paar minute neem om kontakte te sinkroniseer.)"\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg en op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Vertoonopsies"</b></font>" om te verander watter kontakte sigbaar is"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Invoer/uitvoer"</b></font>\n</li></string>
+ <!-- outdated translation 3734101165712848179 --> <string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"Jy het nie enige kontakte om te wys nie. (As jy sopas \'n rekening bygevoeg het, kan dit \'n paar minute neem om kontakte te sinkroniseer.)"\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg en op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Vertoonopsies"</b></font>" om te verander watter kontakte sigbaar is"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Invoer/uitvoer"</b></font>\n</li></string>
+ <!-- outdated translation 6553845386917463292 --> <string name="noContactsNoSimHelpText" product="tablet" msgid="6031363021287849874">"Jy het nie enige kontakte om te wys nie."\n\n" Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg of op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Voer in/uit"</b></font>\n</li></string>
+ <!-- outdated translation 6553845386917463292 --> <string name="noContactsNoSimHelpText" product="default" msgid="467658807711582876">"Jy het nie enige kontakte om te wys nie."\n\n" Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg of op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Voer in/uit"</b></font>\n</li></string>
+ <!-- outdated translation 1122296298361373488 --> <string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"Jy het nie enige kontakte om te wys nie. (As jy sopas \'n rekening bygevoeg het, kan dit \'n paar minute neem om kontakte te sinkroniseer.)"\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg en op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Vertoonopsies"</b></font>" om te verander watter kontakte sigbaar is"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Invoer/uitvoer"</b></font>\n</li></string>
+ <!-- outdated translation 1122296298361373488 --> <string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"Jy het nie enige kontakte om te wys nie. (As jy sopas \'n rekening bygevoeg het, kan dit \'n paar minute neem om kontakte te sinkroniseer.)"\n\n"Om kontakte by te voeg, druk "<font fgcolor="#ffffffff"><b>"Kieslys"</b></font>" en raak:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Rekeninge"</b></font>" om \'n rekening by te voeg en op te stel met kontakte wat jy met die foon kan sinkroniseer"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Vertoonopsies"</b></font>" om te verander watter kontakte sigbaar is"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nuwe kontak"</b></font>" om \'n nuwe kontak van meet af te skep"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Invoer/uitvoer"</b></font>\n</li></string>
+ <string name="noFavoritesHelpText" msgid="3744655776704833277">"Jy het nie enige gunstelinge nie."\n\n" Om \'n kontak by jou lys gunstelinge te voeg:"\n\n" "<li>"Raak die "<b>"Kontakte"</b>"-oortjie"\n</li>" "\n<li>"Raak die kontak wat jy by jou gunstelinge wil voeg"\n</li>" "\n<li>"Raak die ster langs die kontak se naam"\n</li></string>
+ <string name="liveFolder_all_label" msgid="5961411940473276616">"Alle kontakte"</string>
+ <string name="liveFolder_favorites_label" msgid="2674341514070517105">"Gester"</string>
+ <string name="liveFolder_phones_label" msgid="1709786878793436245">"Fone"</string>
+ <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Gebruik raak-nommerbord"</string>
+ <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Keer terug na oproep wat besig is"</string>
+ <string name="dialer_addAnotherCall" msgid="4205688819890074468">"Voeg oproep by"</string>
+ <string name="callDetailTitle" msgid="5340227785196217938">"Oproepdetails"</string>
+ <string name="toast_call_detail_error" msgid="7200975244804730096">"Kon nie details vir die versoekte oproep lees nie."</string>
+ <string name="type_incoming" msgid="6502076603836088532">"Inkomende oproep"</string>
+ <string name="type_outgoing" msgid="343108709599392641">"Uitgaande oproep"</string>
+ <string name="type_missed" msgid="2720502601640509542">"Gemiste oproep"</string>
+ <string name="actionIncomingCall" msgid="6028930669817038600">"Inkomende oproepe"</string>
+ <string name="callBack" msgid="5498224409038809224">"Bel terug"</string>
+ <string name="callAgain" msgid="3197312117049874778">"Bel weer"</string>
+ <string name="returnCall" msgid="8171961914203617813">"Bel terug"</string>
+ <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> min. <xliff:g id="SECONDS">%s</xliff:g> sek."</string>
+ <!-- outdated translation 5007070838253932139 --> <string name="favoritesFrquentSeparator" msgid="8107518433381283736">"Gereeld gebel"</string>
+ <string name="add_contact_dlg_title" msgid="2896685845822146494">"Voeg kontak by"</string>
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Voeg \"<xliff:g id="EMAIL">%s</xliff:g>\" by kontakte?"</string>
+ <string name="description_image_button_one" msgid="1740638037139856139">"een"</string>
+ <string name="description_image_button_two" msgid="5882638439003731308">"twee"</string>
+ <string name="description_image_button_three" msgid="8709731759376015180">"drie"</string>
+ <string name="description_image_button_four" msgid="3530239685642246130">"vier"</string>
+ <string name="description_image_button_five" msgid="1182465427501188413">"vyf"</string>
+ <string name="description_image_button_six" msgid="2093656269261415475">"ses"</string>
+ <string name="description_image_button_seven" msgid="2450357020447676481">"sewe"</string>
+ <string name="description_image_button_eight" msgid="6969435115163287801">"agt"</string>
+ <string name="description_image_button_nine" msgid="7857248695662558323">"nege"</string>
+ <string name="description_image_button_star" msgid="3365919907520767866">"ster"</string>
+ <string name="description_image_button_zero" msgid="4133108949401820710">"nul"</string>
+ <string name="description_image_button_pound" msgid="3039765597595889230">"huts"</string>
+ <!-- no translation found for description_voicemail_button (3402506823655455591) -->
+ <skip />
+ <!-- no translation found for description_dial_button (1274091017188142646) -->
+ <skip />
+ <!-- no translation found for description_delete_button (6263102114033407382) -->
+ <skip />
+ <!-- no translation found for description_digits_edittext (8760207516497016437) -->
+ <skip />
+ <!-- no translation found for description_contact_photo (3387458082667894062) -->
+ <skip />
+ <!-- no translation found for description_minus_button (387136707700230172) -->
+ <skip />
+ <!-- no translation found for description_plus_button (515164827856229880) -->
+ <skip />
+ <!-- outdated translation 5911758680339949273 --> <string name="no_sdcard_title" product="nosdcard" msgid="8543619259870877473">"Geen SD-kaart nie"</string>
+ <string name="no_sdcard_title" product="default" msgid="5911758680339949273">"Geen SD-kaart nie"</string>
+ <!-- outdated translation 6019391476490445358 --> <string name="no_sdcard_message" product="nosdcard" msgid="1334170151822669976">"Geen SD-kaart bespeur nie"</string>
+ <string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Geen SD-kaart bespeur nie"</string>
+ <string name="searching_vcard_title" msgid="4970508055399376813">"Soek vir vCard"</string>
+ <string name="import_from_sim" msgid="3859272228033941659">"Voer in van SIM-kaart"</string>
+ <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Voer in van SD-kaart"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Voer in van SD-kaart"</string>
+ <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Voer uit na SD-kaart"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Voer uit na SD-kaart"</string>
+ <!-- no translation found for share_visible_contacts (890150378880783797) -->
+ <skip />
+ <string name="import_one_vcard_string" msgid="9059163467020328433">"Voer een vCard-lêer in"</string>
+ <string name="import_multiple_vcard_string" msgid="3810226492811062392">"Voer meerdere vCard-lêers in"</string>
+ <string name="import_all_vcard_string" msgid="5518136113853448474">"Voer alle vCard-lêers in"</string>
+ <!-- outdated translation 6917522333561434546 --> <string name="searching_vcard_message" product="nosdcard" msgid="996170203695743981">"Soek vir vCard-data op SD-kaart"</string>
+ <string name="searching_vcard_message" product="default" msgid="6917522333561434546">"Soek vir vCard-data op SD-kaart"</string>
+ <!-- outdated translation 3506782007953167180 --> <string name="scanning_sdcard_failed_title" product="nosdcard" msgid="6957414493948497249">"Kon nie SD-kaart ondersoek nie"</string>
+ <string name="scanning_sdcard_failed_title" product="default" msgid="3506782007953167180">"Kon nie SD-kaart ondersoek nie"</string>
+ <!-- no translation found for scanning_sdcard_failed_message (4106156155205860626) -->
+ <skip />
+ <string name="scanning_sdcard_failed_message" product="default" msgid="3761992500690182922">"Kon nie SD-kaart ondersoek nie (Rede: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"T/A-fout"</string>
+ <!-- no translation found for fail_reason_low_memory_during_import (7514918659342886381) -->
+ <skip />
+ <string name="fail_reason_vcard_parse_error" msgid="1201233722762680214">"Kon om \'n onverwagse rede nie vCard ontleed nie"</string>
+ <!-- no translation found for fail_reason_not_supported (294499264620201243) -->
+ <skip />
+ <!-- no translation found for vcard_import_failed (7718330063493653085) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (6339234836196984924) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (1730986357514922756) -->
+ <skip />
+ <!-- no translation found for fail_reason_failed_to_collect_vcard_meta_info (4154492282316067754) -->
+ <skip />
+ <string name="fail_reason_failed_to_read_files" msgid="3659521123567134029">"Een of meer lêers kon nie ingevoer word nie (%s)."</string>
+ <string name="fail_reason_unknown" msgid="999034019513096768">"Onbekende fout"</string>
+ <string name="select_vcard_title" msgid="3968948173786172468">"Kies vCard-lêer"</string>
+ <!-- no translation found for caching_vcard_title (5009556022082659780) -->
+ <skip />
+ <!-- no translation found for caching_vcard_message (2380844718093378900) -->
+ <skip />
+ <!-- no translation found for progress_notifier_message (2311011466908220528) -->
+ <skip />
+ <!-- no translation found for importing_vcard_description (4245275224298571351) -->
+ <skip />
+ <!-- outdated translation 4923008144735294994 --> <string name="reading_vcard_failed_title" msgid="2162610359561887043">"Kon nie vCard-data lees nie"</string>
+ <!-- no translation found for reading_vcard_canceled_title (1770608329958463131) -->
+ <skip />
+ <!-- no translation found for importing_vcard_finished_title (3341541727268747967) -->
+ <skip />
+ <!-- no translation found for importing_vcard_canceled_title (6367906965439777280) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message (2804911199145873396) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message_with_default_name (1022969530654129470) -->
+ <skip />
+ <!-- no translation found for vcard_import_request_rejected_message (2592424820635325951) -->
+ <skip />
+ <!-- no translation found for vcard_export_will_start_message (2210241345252081463) -->
+ <skip />
+ <!-- no translation found for vcard_export_request_rejected_message (8259494002258326330) -->
+ <skip />
+ <!-- no translation found for vcard_unknown_filename (7171709890959915954) -->
+ <skip />
+ <!-- no translation found for percentage (34897865327092209) -->
+ <skip />
+ <string name="confirm_export_title" msgid="7648747763127442983">"Bevestig uitvoer"</string>
+ <string name="confirm_export_message" msgid="3875683519257829750">"Is jy seker jy wil jou kontaklys uitvoer na \"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\"?"</string>
+ <string name="exporting_contact_failed_title" msgid="585823094820602526">"Kon nie kontakdata uitvoer nie"</string>
+ <string name="exporting_contact_failed_message" msgid="4151348002470298092">"Kon nie kontakdata uitvoer nie."\n"Rede vir mislukking: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_no_exportable_contact" msgid="4919714086648344495">"Daar is geen uitvoerbare kontak nie"</string>
+ <!-- outdated translation 7084146295639672658 --> <string name="fail_reason_too_many_vcard" product="nosdcard" msgid="3745507837635270265">"Te veel vCard-lêers op die SD-kaart"</string>
+ <string name="fail_reason_too_many_vcard" product="default" msgid="7084146295639672658">"Te veel vCard-lêers op die SD-kaart"</string>
+ <string name="fail_reason_too_long_filename" msgid="1915716071321839166">"Vereiste lêernaam is te lank (\"<xliff:g id="FILENAME">%s</xliff:g>\")"</string>
+ <!-- no translation found for exporting_vcard_finished_title (4259736138838583213) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_canceled_title (1827672399438062140) -->
+ <skip />
+ <string name="exporting_contact_list_title" msgid="9072240631534457415">"Voer kontakdata uit"</string>
+ <string name="exporting_contact_list_message" msgid="5640326540405486055">"Voer kontakdata uit na \"<xliff:g id="FILE_NAME">%s</xliff:g>\""</string>
+ <string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">"Kon nie die uitvoerder inisialiseer nie: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"Fout het voorgekom tydens uitvoer: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="composer_failed_to_get_database_infomation" msgid="3723109558155169053">"Kon nie databasisinligting kry nie"</string>
+ <!-- outdated translation 2239503301380653777 --> <string name="composer_has_no_exportable_contact" product="tablet" msgid="5161491059051198932">"Daar is geen uitvoerbare kontak nie. Jy kan ook nie-uitvoerbare data kies"</string>
+ <!-- outdated translation 2239503301380653777 --> <string name="composer_has_no_exportable_contact" product="default" msgid="322344221706924358">"Daar is geen uitvoerbare kontak nie. Jy kan ook nie-uitvoerbare data kies"</string>
+ <string name="composer_not_initialized" msgid="8041534450748388843">"Die vCard-skepper is nie korrek geïnisialiseer nie"</string>
+ <string name="fail_reason_could_not_open_file" msgid="4013520943128739511">"Kon nie \"<xliff:g id="FILE_NAME">%s</xliff:g>\" open nie: <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> van <xliff:g id="TOTAL_NUMBER">%s</xliff:g> kontakte"</string>
+ <!-- no translation found for cancel_import_confirmation_title (5578683596010294836) -->
+ <skip />
+ <!-- no translation found for cancel_import_confirmation_message (8560937090143057107) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_title (6516467140276768528) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_message (1392976902396351957) -->
+ <skip />
+ <!-- no translation found for cancel_vcard_import_or_export_failed (7096533244663846810) -->
+ <skip />
+ <string name="search_settings_description" msgid="2675223022992445813">"Name van jou kontakte"</string>
+ <string name="add_2sec_pause" msgid="9214012315201040129">"Voeg 2-sek.-pouse by"</string>
+ <string name="add_wait" msgid="3360818652790319634">"Voeg wagtyd by"</string>
+ <string name="call_disambig_title" msgid="1911302597959335178">"Bel met"</string>
+ <string name="sms_disambig_title" msgid="4675399294513152364">"Teks met"</string>
+ <string name="make_primary" msgid="5829291915305113983">"Onthou hierdie keuse"</string>
+ <string name="quickcontact_missing_app" msgid="4600366393134289038">"Geen program gevind om hierdie handeling te hanteer nie"</string>
+ <string name="quickcontact_remember_choice" msgid="5964536411579749424">"Onthou hierdie keuse"</string>
+ <string name="quickcontact_missing_name" msgid="5590266114306996632">"Onbekend"</string>
+ <!-- no translation found for quickcontact_no_data (2098000859125253675) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_description (3792792870662989100) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_caption (4287306111861545753) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_button (8728754360205289059) -->
+ <skip />
+ <string name="menu_accounts" msgid="8499114602017077970">"Rekeninge"</string>
+ <string name="menu_import_export" msgid="3765725645491577190">"Voer in/uit"</string>
+ <string name="dialog_import_export" msgid="4771877268244096596">"Voer kontakte in/uit"</string>
+ <!-- outdated translation 943789700636542260 --> <string name="menu_share" msgid="8746849630474240344">"Deel"</string>
+ <string name="share_via" msgid="563121028023030093">"Deel kontak via"</string>
+ <string name="share_error" msgid="4374508848981697170">"Hierdie kontak kan nie gedeel word nie."</string>
+ <string name="nameLabelsGroup" msgid="2034640839640477827">"Naam"</string>
+ <string name="nicknameLabelsGroup" msgid="2891682101053358010">"Bynaam"</string>
+ <string name="organizationLabelsGroup" msgid="2478611760751832035">"Organisasie"</string>
+ <string name="websiteLabelsGroup" msgid="4202998982804009261">"Webwerf"</string>
+ <string name="eventLabelsGroup" msgid="8069912895912714412">"Gebeurtenis"</string>
+ <!-- no translation found for relationLabelsGroup (1854373894284572781) -->
+ <skip />
+ <!-- no translation found for groupsLabel (8573535366319059326) -->
+ <skip />
+ <string name="type_short_home" msgid="7770424864090605384">"H"</string>
+ <string name="type_short_mobile" msgid="1655473281466676216">"M"</string>
+ <string name="type_short_work" msgid="4925330752504537861">"W"</string>
+ <string name="type_short_pager" msgid="2613818970827594238">"P"</string>
+ <string name="type_short_other" msgid="5669407180177236769">"O"</string>
+ <string name="dialog_new_contact_account" msgid="9044704073286262197">"Skep kontak onder rekening"</string>
+ <string name="menu_sync_remove" msgid="3266725887008450161">"Verwyder sinkroniseergroep"</string>
+ <string name="dialog_sync_add" msgid="8267045393119375803">"Voeg sinkroniseergroep by"</string>
+ <string name="display_more_groups" msgid="2682547080423434170">"Meer groepe..."</string>
+ <string name="display_ungrouped" msgid="4602580795576261158">"Alle ander kontakte"</string>
+ <string name="display_all_contacts" msgid="6846131371214707956">"Alle kontakte"</string>
+ <string name="display_warn_remove_ungrouped" msgid="2314043155909167610">"As jy \'<xliff:g id="GROUP">%s</xliff:g>\' uit sinkronisering verwyder, sal dit ook enige ongegroepeerde kontakte uit sinkronisering verwyder."</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="tablet" msgid="7946049152658522054">"Slegs foon (ongesinkroniseer)"</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="default" msgid="3682950835276226870">"Slegs foon (ongesinkroniseer)"</string>
+ <string name="call_custom" msgid="7756571794763171802">"Bel <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="call_home" msgid="1990519474420545392">"Bel tuis"</string>
+ <string name="call_mobile" msgid="7502236805487609178">"Bel selfoon"</string>
+ <string name="call_work" msgid="5328785911463744028">"Bel werk"</string>
+ <string name="call_fax_work" msgid="7467763592359059243">"Bel werkfaks"</string>
+ <string name="call_fax_home" msgid="8342175628887571876">"Bel huisfaks"</string>
+ <string name="call_pager" msgid="9003902812293983281">"Bel roeper"</string>
+ <!-- outdated translation 5605584621798108205 --> <string name="call_other" msgid="8563753966926932052">"Bel ander"</string>
+ <string name="call_callback" msgid="1910165691349426858">"Bel - terugbel"</string>
+ <string name="call_car" msgid="3280537320306436445">"Bel motor"</string>
+ <string name="call_company_main" msgid="6105120947138711257">"Bel maatskappy, hoof"</string>
+ <string name="call_isdn" msgid="1541590690193403411">"Bel ISDN"</string>
+ <string name="call_main" msgid="6082900571803441339">"Bel hoof"</string>
+ <!-- outdated translation 7777261153532968503 --> <string name="call_other_fax" msgid="5745314124619636674">"Bel ander faks"</string>
+ <string name="call_radio" msgid="8296755876398357063">"Bel radio"</string>
+ <string name="call_telex" msgid="2223170774548648114">"Bel teleks"</string>
+ <string name="call_tty_tdd" msgid="8951266948204379604">"Oproep-TTY/TDD"</string>
+ <string name="call_work_mobile" msgid="8707874281430105394">"Bel werkselfoon"</string>
+ <string name="call_work_pager" msgid="3419348514157949008">"Bel werkroeper"</string>
+ <string name="call_assistant" msgid="2141641383068514308">"Bel <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="call_mms" msgid="6274041545876221437">"Bel MMS"</string>
+ <string name="sms_custom" msgid="5932736853732191825">"Teks <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="sms_home" msgid="7524332261493162995">"Teks - tuis"</string>
+ <string name="sms_mobile" msgid="5200107250451030769">"Teks - selfoon"</string>
+ <string name="sms_work" msgid="2269624156655267740">"Teks - werk"</string>
+ <string name="sms_fax_work" msgid="8028189067816907075">"Teks - werkfaks"</string>
+ <string name="sms_fax_home" msgid="9204042076306809634">"Teks - huisfaks"</string>
+ <string name="sms_pager" msgid="7730404569637015192">"Teks - roeper"</string>
+ <!-- outdated translation 5131921487474531617 --> <string name="sms_other" msgid="806127844607642331">"Teks - ander"</string>
+ <string name="sms_callback" msgid="5004824430094288752">"Teks-terugbel"</string>
+ <string name="sms_car" msgid="7444227058437359641">"Teks - motor"</string>
+ <string name="sms_company_main" msgid="118970873419678087">"Teks - maatskappy, hoof"</string>
+ <string name="sms_isdn" msgid="8153785037515047845">"Teks - ISDN"</string>
+ <string name="sms_main" msgid="8621625784504541679">"Teks - hoof"</string>
+ <!-- outdated translation 3930666870074006114 --> <string name="sms_other_fax" msgid="3888842199855843152">"Teks - ander faks"</string>
+ <string name="sms_radio" msgid="3329166673433967820">"Teks - radio"</string>
+ <string name="sms_telex" msgid="9034802430065267848">"Teks - teleks"</string>
+ <string name="sms_tty_tdd" msgid="6782284969132531532">"Teks - TTY/TDD"</string>
+ <string name="sms_work_mobile" msgid="2459939960512702560">"Teks - werkselfoon"</string>
+ <string name="sms_work_pager" msgid="5566924423316960597">"Teks - werkroeper"</string>
+ <string name="sms_assistant" msgid="2773424339923116234">"Teks <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="sms_mms" msgid="4069352461380762677">"Teks - MMS"</string>
+ <string name="email_home" msgid="8573740658148184279">"E-postuis"</string>
+ <string name="email_mobile" msgid="2042889209787989814">"E-pos - mobiel"</string>
+ <string name="email_work" msgid="2807430017302722689">"E-pos - werk"</string>
+ <!-- outdated translation 8093933498541795832 --> <string name="email_other" msgid="3454004077967657109">"E-pos ander"</string>
+ <string name="email_custom" msgid="7548003991586214105">"E-pos <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="email" msgid="5668400997660065897">"E-pos"</string>
+ <string name="map_home" msgid="1243547733423343982">"Sien huisadres"</string>
+ <string name="map_work" msgid="1360474076921878088">"Sien werkadres"</string>
+ <!-- outdated translation 5560707927535653892 --> <string name="map_other" msgid="3817820803587012641">"Sien ander adres"</string>
+ <string name="map_custom" msgid="6184363799976265281">"Sien <xliff:g id="CUSTOM">%s</xliff:g> adres"</string>
+ <string name="chat_aim" msgid="2588492205291249142">"Klets met AIM"</string>
+ <string name="chat_msn" msgid="8041633440091073484">"Klets met Windows Live"</string>
+ <string name="chat_yahoo" msgid="6629211142719943666">"Klets met Yahoo"</string>
+ <string name="chat_skype" msgid="1210045020427480566">"Klets met Skype"</string>
+ <string name="chat_qq" msgid="4294637812847719693">"Klets met QQ"</string>
+ <string name="chat_gtalk" msgid="981575737258117697">"Klets met Google Talk"</string>
+ <string name="chat_icq" msgid="8438405386153745775">"Klets met ICQ"</string>
+ <string name="chat_jabber" msgid="7561444230307829609">"Klets met Jabber"</string>
+ <string name="chat" msgid="9025361898797412245">"Klets"</string>
+ <!-- no translation found for postal_address (8765560217149624536) -->
+ <skip />
+ <string name="postal_street" msgid="8133143961580058972">"Straat"</string>
+ <string name="postal_pobox" msgid="4431938829180269821">"Posbus"</string>
+ <string name="postal_neighborhood" msgid="1450783874558956739">"Buurt"</string>
+ <string name="postal_city" msgid="6597491300084895548">"Stad"</string>
+ <string name="postal_region" msgid="6045263193478437672">"Deelstaat"</string>
+ <string name="postal_postcode" msgid="572136414136673751">"Poskode"</string>
+ <string name="postal_country" msgid="7638264508416368690">"Land"</string>
+ <!-- no translation found for full_name (6602579550613988977) -->
+ <skip />
+ <string name="name_given" msgid="1687286314106019813">"Voornaam"</string>
+ <string name="name_family" msgid="3416695586119999058">"Van"</string>
+ <string name="name_prefix" msgid="59756378548779822">"Naamvoorvoegsel"</string>
+ <string name="name_middle" msgid="8467433655992690326">"Middelnaam"</string>
+ <string name="name_suffix" msgid="3855278445375651441">"Naamagtervoegsel"</string>
+ <string name="name_phonetic_given" msgid="6853570431394449191">"Fonetiese voornaam"</string>
+ <string name="name_phonetic_middle" msgid="8643721493320405200">"Fonetiese middelnaam"</string>
+ <string name="name_phonetic_family" msgid="462095502140180305">"Fonetiese van"</string>
+ <!-- no translation found for name_phonetic (4259595234312430484) -->
+ <skip />
+ <string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kontak"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
+ <string name="use_photo_as_primary" msgid="8807110122951157246">"Gebruik hierdie foto"</string>
+ <string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> kontakinligting is nie op hierdie toestel redigeerbaar nie."</string>
+ <string name="no_contact_details" msgid="6754415338321837001">"Geen bykomende inligting vir hierdie kontak nie"</string>
+ <!-- no translation found for display_options_sort_list_by (6080091755852211076) -->
+ <skip />
+ <!-- no translation found for display_options_sort_by_given_name (184916793466387067) -->
+ <skip />
+ <!-- no translation found for display_options_sort_by_family_name (7857986975275712622) -->
+ <skip />
+ <!-- no translation found for display_options_view_names_as (18022868169627979) -->
+ <skip />
+ <!-- no translation found for display_options_view_given_name_first (6968288511197363292) -->
+ <skip />
+ <!-- no translation found for display_options_view_family_name_first (1447288164951453714) -->
+ <skip />
+ <!-- no translation found for search_bar_hint (1012756309632856553) -->
+ <skip />
+ <!-- no translation found for search_for_all_contacts (6644963335787294131) -->
+ <skip />
+ <!-- no translation found for take_photo (7496128293167402354) -->
+ <skip />
+ <!-- no translation found for take_new_photo (7341354729436576304) -->
+ <skip />
+ <!-- no translation found for pick_photo (448886509158039462) -->
+ <skip />
+ <!-- no translation found for pick_new_photo (7962368009197147617) -->
+ <skip />
+ <!-- no translation found for locale_change_in_progress (7583992153091537467) -->
+ <skip />
+ <!-- no translation found for upgrade_in_progress (474511436863451061) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory (6153384328042175667) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory_uninstall (1721798828992091432) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory_retry (8431289830472724609) -->
+ <skip />
+ <!-- no translation found for search_results_searching (7755623475227227314) -->
+ <skip />
+ <!-- no translation found for menu_display_selected (6470001164297969034) -->
+ <skip />
+ <!-- no translation found for menu_display_all (8887488642609786198) -->
+ <skip />
+ <!-- no translation found for menu_select_all (621719255150713545) -->
+ <skip />
+ <!-- no translation found for menu_select_none (7093222469852132345) -->
+ <skip />
+ <!-- no translation found for multiple_picker_title:one (4761009734586319101) -->
+ <!-- no translation found for multiple_picker_title:other (4608837420986126229) -->
+ <!-- no translation found for no_contacts_selected (5877803471037324613) -->
+ <skip />
+ <!-- no translation found for add_field (2384260056674995230) -->
+ <skip />
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
+ <!-- no translation found for contact_status_update_attribution (752179367353018597) -->
+ <skip />
+ <!-- no translation found for contact_status_update_attribution_with_date (7358045508107825068) -->
+ <skip />
+ <!-- no translation found for description_star (2605854427360036550) -->
+ <skip />
+ <!-- no translation found for edit_contact (7529281274005689512) -->
+ <skip />
+ <!-- no translation found for merge_info:one (148365587896371969) -->
+ <!-- no translation found for merge_info:other (425683718017380845) -->
+ <!-- no translation found for local_invisible_directory (6046691709127661065) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_title (5276699501316246253) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_message (3842757977671434836) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_title (1064042382692091314) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_message (6549585283910518095) -->
+ <skip />
+ <!-- no translation found for menu_copyContact (4401683725471696686) -->
+ <skip />
+ <!-- no translation found for contact_directory_description (683398073603909119) -->
+ <skip />
+ <!-- no translation found for search_label (6789295859496641042) -->
+ <skip />
+ <!-- no translation found for directory_search_label (1887759056597975053) -->
+ <skip />
+ <!-- no translation found for local_search_label (1686089693064201315) -->
+ <skip />
+ <!-- no translation found for toast_making_personal_copy (7905283986345263275) -->
+ <skip />
+ <!-- no translation found for list_filter_prompt (7481426622828055116) -->
+ <skip />
+ <!-- no translation found for list_filter_all_accounts (8908683398914322369) -->
+ <skip />
+ <!-- no translation found for list_filter_all_starred (5031734941601931356) -->
+ <skip />
+ <!-- no translation found for list_filter_custom (8910173055702057002) -->
+ <skip />
+ <!-- no translation found for list_filter_customize (2035084418635775579) -->
+ <skip />
+ <!-- no translation found for list_filter_phones (7905045603593508221) -->
+ <skip />
+ <!-- no translation found for list_filter_single (5871400283515893087) -->
+ <skip />
+ <!-- no translation found for custom_list_filter (7836035257402013957) -->
+ <skip />
+ <!-- no translation found for activity_title_settings (5464130076132770781) -->
+ <skip />
+ <!-- no translation found for menu_settings (377929915873428211) -->
+ <skip />
+ <!-- no translation found for preference_displayOptions (1341720270148252393) -->
+ <skip />
+ <!-- no translation found for organization_company_and_title (6718207751363732025) -->
+ <skip />
+ <!-- no translation found for hint_findContacts (1808681193458772072) -->
+ <skip />
+ <!-- no translation found for non_phone_caption (1541655052330027380) -->
+ <skip />
+ <!-- no translation found for non_phone_add_to_contacts (6590985286250471169) -->
+ <skip />
+ <!-- no translation found for non_phone_close (7608506439725515667) -->
+ <skip />
+ <!-- no translation found for widget_name_and_phonetic (8739586586600099979) -->
+ <skip />
+ <!-- no translation found for date_year_toggle (7356532842767854606) -->
+ <skip />
+ <!-- no translation found for social_widget_label (6378905543028924592) -->
+ <skip />
+ <!-- no translation found for social_widget_loading (3697996166985327861) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_create_contact (7014525713871959208) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_add_account (7911101713860139754) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_import_contacts (4456440183590517471) -->
+ <skip />
+ <!-- no translation found for create_group_dialog_title (6874527142828424475) -->
+ <skip />
+ <!-- no translation found for create_group_item_label (5218022006186243310) -->
+ <skip />
+ <!-- no translation found for rename_group_dialog_title (3765299704290513289) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_title (7368429698398624427) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_message (295063284548750881) -->
+ <skip />
+ <!-- no translation found for toast_join_with_empty_contact (5015189525953438968) -->
+ <skip />
+ <!-- no translation found for indicator_joined_contact (3321049349627022128) -->
+ <skip />
+ <!-- no translation found for toast_text_copied (5143776250008541719) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_title (3950463632415908534) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_message (7021968394611740251) -->
+ <skip />
+ <!-- no translation found for discard (1234315037371251414) -->
+ <skip />
+</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
new file mode 100644
index 0000000..1684a05
--- /dev/null
+++ b/res/values-am/strings.xml
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sharedUserLabel" msgid="7965035505237135241">"Android ኮር ትግበራ"</string>
+ <!-- no translation found for contactsList (8661624236494819731) -->
+ <skip />
+ <string name="launcherDialer" msgid="8636288196618486553">"ስልክ"</string>
+ <!-- no translation found for shortcutContact (749243779392912958) -->
+ <skip />
+ <string name="shortcutDialContact" msgid="746622101599186779">"ቀጥታ ደውል"</string>
+ <string name="shortcutMessageContact" msgid="2460337253595976198">"ቀጥታ መልዕክት"</string>
+ <string name="shortcutActivityTitle" msgid="6642877210643565436">"የዕውቂያአቋራጭ ምረጥ"</string>
+ <string name="callShortcutActivityTitle" msgid="6065749861423648991">"ለመደወል ቁጥር ምረጥ"</string>
+ <string name="messageShortcutActivityTitle" msgid="3084542316620335911">"መልዕክትለመላክ ቁጥር ምረጥ"</string>
+ <!-- no translation found for contactPickerActivityTitle (6886592363525235031) -->
+ <skip />
+ <!-- no translation found for starredList (4817256136413959463) -->
+ <skip />
+ <!-- no translation found for frequentList (7154768136473953056) -->
+ <skip />
+ <!-- no translation found for strequentList (5640192862059373511) -->
+ <skip />
+ <!-- no translation found for viewContactTitle (7989394521836644384) -->
+ <skip />
+ <!-- no translation found for viewContactDesription (214186610887547860) -->
+ <skip />
+ <!-- no translation found for editContactDescription (2947202828256214947) -->
+ <skip />
+ <!-- no translation found for insertContactDescription (4709878105452681987) -->
+ <skip />
+ <!-- no translation found for searchHint (8482945356247760701) -->
+ <skip />
+ <string name="menu_search" msgid="9147752853603483719">"ፍለጋ"</string>
+ <!-- no translation found for menu_newContact (1209922412763274638) -->
+ <skip />
+ <!-- no translation found for menu_viewContact (2795575601596468581) -->
+ <skip />
+ <string name="menu_callNumber" msgid="5142851348489387516">"ጥሪ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for menu_addStar (2908478235715404876) -->
+ <skip />
+ <!-- no translation found for menu_removeStar (5844227078364227030) -->
+ <skip />
+ <!-- no translation found for menu_editContact (3452858480713561396) -->
+ <skip />
+ <!-- no translation found for menu_deleteContact (1916555454274101750) -->
+ <skip />
+ <string name="menu_call" msgid="3992595586042260618">"የጥሪ ዕውቂያ"</string>
+ <string name="menu_sendSMS" msgid="5535886767547006515">"ዕውቂያ ፃፍ"</string>
+ <string name="menu_makeDefaultEmail" msgid="2599044610375789994">"ነባሪ ኢሜይል አድርግ"</string>
+ <string name="menu_splitAggregate" msgid="8368636463748691868">"ለይ"</string>
+ <!-- no translation found for menu_renameGroup (2798886925154156075) -->
+ <skip />
+ <!-- no translation found for menu_deleteGroup (644571524292675446) -->
+ <skip />
+ <!-- no translation found for menu_new_contact_action_bar (8887818026717394343) -->
+ <skip />
+ <string name="splitConfirmation_title" msgid="6716467920283502570">"ዕውቂያ ለይ"</string>
+ <string name="splitConfirmation" msgid="1150797297503944823">"ይህን ነጠላ ዕውቂያ ወደ ብዙ ዕውቂያዎች ለመክፈል በእርግጥ ይፈልጋሉ፡ለተቀላቀለው እያንዳንዱ ዕውቂያ መረጃ አንድ?"</string>
+ <string name="menu_joinAggregate" msgid="5027981918265667970">"አገናኝ"</string>
+ <string name="titleJoinContactDataWith" msgid="7684875775798635354">"ዕውቄያዎችን አገናኝ"</string>
+ <string name="blurbJoinContactDataWith" msgid="995870557595050304">"ከ<xliff:g id="NAME">%s</xliff:g> ጋር ለመቀላቀል የሚፈልጉትን ዕውቂያ ይምረጡ።"</string>
+ <string name="showAllContactsJoinItem" msgid="2189695051430392383">"ሁሉንም ዕውቂያዎች አሳይ"</string>
+ <string name="separatorJoinAggregateSuggestions" msgid="2831414448851313345">"አስተያየት የተሰጠባቸው እውቅያዎች"</string>
+ <string name="separatorJoinAggregateAll" msgid="7939932265026181043">"ሁሉም እውቅያዎች"</string>
+ <string name="contactsJoinedMessage" msgid="7208148163607047389">"ዕውቂያዎች ተገናኝተዋል"</string>
+ <string name="menu_contactOptions" msgid="1957061455705020617">"አማራጮች"</string>
+ <string name="contactOptionsTitle" msgid="8259347644090700915">"አማራጮች"</string>
+ <!-- no translation found for deleteConfirmation_title (6394309508930335204) -->
+ <skip />
+ <string name="readOnlyContactWarning" msgid="1390849295342594265">"ዕውቂያዎችን ከንባብ-ብቻ መለያዎች መሰረዝ አይችሉም፤ ነገር ግን በዕውቂያ ዝርዝሮችዎ ውስጥ መደበቅ ይችላሉ።"</string>
+ <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"ይህ ዕውቂያ ከብዙ መለያዎች መረጃ ይዟል።ከንባብ-ብቻ መለያዎች ውስጥ ያሉ ዕውቂያዎች ይደበቃሉ፣አይሰረዙም።"</string>
+ <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"ይህን ዕውቂያ መሰረዝ ከብዙ መለያዎች ውስጥ መረጃ ይሰርዛል።"</string>
+ <!-- no translation found for deleteConfirmation (811706994761610640) -->
+ <skip />
+ <string name="menu_done" msgid="796017761764190697">"ተከናውኗል"</string>
+ <!-- outdated translation 2174577548513895144 --> <string name="menu_doNotSave" msgid="58593876893538465">"አድህር"</string>
+ <!-- no translation found for editContact_title_edit (7678695190666836093) -->
+ <skip />
+ <!-- no translation found for editContact_title_insert (9125600232291405757) -->
+ <skip />
+ <string name="label_phonetic_name" msgid="2288082649573927286">"ድምፀ ልሳን"</string>
+ <!-- no translation found for label_notes (8337354953278341042) -->
+ <skip />
+ <string name="label_sip_address" msgid="124073911714324974">"የበይነመረብ ጥሪ"</string>
+ <!-- no translation found for label_ringtone (8833166825330686244) -->
+ <skip />
+ <string name="ghostData_phonetic_name" msgid="7852749081984070902">"የድምፀ ልሳን ስም"</string>
+ <!-- no translation found for ghostData_company (5414421120553765775) -->
+ <skip />
+ <string name="ghostData_title" msgid="7496735200318496110">"አርዕስት"</string>
+ <!-- no translation found for invalidContactMessage (5816991830260044593) -->
+ <skip />
+ <!-- no translation found for pickerNewContactHeader (7750705279843568147) -->
+ <skip />
+ <!-- no translation found for phoneLabelsGroup (6468091477851199285) -->
+ <skip />
+ <!-- no translation found for emailLabelsGroup (8389931313045344406) -->
+ <skip />
+ <!-- no translation found for imLabelsGroup (3898238486262614027) -->
+ <skip />
+ <!-- no translation found for postalLabelsGroup (3487738141112589324) -->
+ <skip />
+ <string-array name="otherLabels">
+ <item msgid="8287841928119937597">"መስርያ ቤት"</item>
+ <item msgid="7196592230748086755">"ማስታወሻ"</item>
+ </string-array>
+ <!-- no translation found for photoPickerNotFoundText (6247290728908599701) -->
+ <skip />
+ <!-- no translation found for photoPickerNotFoundText (431331662154342581) -->
+ <skip />
+ <!-- no translation found for attach_photo_dialog_title (5599827035558557169) -->
+ <skip />
+ <string name="customLabelPickerTitle" msgid="1081475101983255212">"ብጁ መሰየሚያ ስም"</string>
+ <string name="menu_displayGroup" msgid="5655505437727616553">"ማሳያ አማራጮች"</string>
+ <string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"ጥሪዎችን በቀጥታ ወደ ድምፅ መልዕክት ላክ"</string>
+ <!-- no translation found for default_ringtone (9099988849649827972) -->
+ <skip />
+ <!-- no translation found for removePhoto (4898105274130284565) -->
+ <skip />
+ <!-- no translation found for noContacts (8579310973261953559) -->
+ <skip />
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
+ <string name="noMatchingContacts" msgid="4266283206853990471">"ምንም ተዛማጅ ዕውቂያዎች አልተገኙም።"</string>
+ <!-- no translation found for noContactsWithPhoneNumbers (1605457050218824269) -->
+ <skip />
+ <string name="showFilterPhones" msgid="4184858075465653970">"ከስልክ ጋር ያሉ እውቂያዎች ብቻ"</string>
+ <string name="showFilterPhonesDescrip" msgid="6644443248815191067">"ስልክ ቁጥር ያላቸውን ዕውቂያዎች ብቻ አሳይ"</string>
+ <string name="headerContactGroups" msgid="2426134991932503843">"ለማሳየት ዕውቂያዎች ምረጥ"</string>
+ <plurals name="groupDescrip">
+ <item quantity="other" msgid="3507881585720628389">"<xliff:g id="COUNT">%0$d</xliff:g> እውቅያዎች"</item>
+ </plurals>
+ <plurals name="groupDescripPhones">
+ <item quantity="other" msgid="3816047547470490208">"<xliff:g id="COUNT_0">%1$d</xliff:g>ዕውቂያዎች፣<xliff:g id="COUNTWITHPHONES">%2$d</xliff:g> ከስልክ ጋር"</item>
+ </plurals>
+ <string name="savingContact" msgid="4075751076741924939">"ዕውቂያ በማስቀመጥ ላይ..."</string>
+ <string name="savingDisplayGroups" msgid="2133152192716475939">"ማሳያ አማራጮችን በማስቀመጥ ላይ..."</string>
+ <!-- no translation found for contactSavedToast (7152589189385441091) -->
+ <skip />
+ <string name="contactSavedErrorToast" msgid="9189098776225004666">"ስህተት፣የዕውቂያለውጦችን ለማስቀመጥአልተቻለም።"</string>
+ <plurals name="listTotalPhoneContacts">
+ <item quantity="one" msgid="3015357862286673986">"1 ዕውቂያ ከስልክ ቁጥር ጋር"</item>
+ <item quantity="other" msgid="3299954047880968205">"<xliff:g id="COUNT">%d</xliff:g> ዕውቂያዎች ከስልክ ቁጥሮች ጋር"</item>
+ </plurals>
+ <!-- outdated translation 2756295259674938869 --> <string name="listTotalPhoneContactsZero" msgid="6968813857632984319">"ከስልክ ቁጥር ጋር የሚታይ ዕውቂያዎች የሉም"</string>
+ <plurals name="listTotalAllContacts">
+ <item quantity="one" msgid="3405747744700823280">"1 እውቅያ"</item>
+ <item quantity="other" msgid="3578469907265375314">"<xliff:g id="COUNT">%d</xliff:g> እውቅያዎች"</item>
+ </plurals>
+ <!-- outdated translation 6811347506748072822 --> <string name="listTotalAllContactsZero" msgid="1889349925514589304">"ምንም የሚታይ ዕውቂያዎች የሉም"</string>
+ <!-- no translation found for listTotalAllContactsZeroCustom (4058252141420128998) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroStarred (5391630590684099117) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroGroup (5448979458248027615) -->
+ <skip />
+ <plurals name="listFoundAllContacts">
+ <item quantity="one" msgid="5517063038754171134">"1 ተገኝቷል"</item>
+ <item quantity="other" msgid="3852668542926965042">"<xliff:g id="COUNT">%d</xliff:g> ተገኝቷል"</item>
+ </plurals>
+ <string name="foundTooManyContacts" msgid="2548148047461758967">"ከ<xliff:g id="COUNT">%d</xliff:g> የበለጠ ተገኝቷል"</string>
+ <string name="listFoundAllContactsZero" msgid="777952841930508289">"አልተገኘም"</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one" msgid="4826918429708286628">"1 ተገኝቷል"</item>
+ <item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> ተገኝቷል"</item>
+ </plurals>
+ <!-- no translation found for contactsIconLabel (7666609097606552806) -->
+ <skip />
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
+ <!-- no translation found for contactsFavoritesLabel (8417039765586853670) -->
+ <skip />
+ <string name="dialerIconLabel" msgid="6500826552823403796">"ስልክ"</string>
+ <!-- no translation found for recentCallsIconLabel (1419116422359067949) -->
+ <skip />
+ <string name="liveFolderAll" msgid="4789010460767506206">"ሁሉም እውቅያዎች"</string>
+ <string name="liveFolderFavorites" msgid="3100957542927222282">"ባለኮከብ ዕውቂያዎች"</string>
+ <string name="liveFolderPhone" msgid="3739376066610926780">"ዕውቂያዎችከስልክ ቁጥሮች ጋር"</string>
+ <string name="menu_sendTextMessage" msgid="6937343460284499306">"የፅሁፍ መልዕክት ላክ"</string>
+ <string name="recentCalls_callNumber" msgid="1756372533999226126">"ጥሪ <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for recentCalls_editNumberBeforeCall (7756171675833267857) -->
+ <skip />
+ <!-- no translation found for recentCalls_addToContact (1429899535546487008) -->
+ <skip />
+ <!-- no translation found for recentCalls_removeFromRecentList (401662244636511330) -->
+ <skip />
+ <!-- no translation found for recentCalls_deleteAll (6352364392762163704) -->
+ <skip />
+ <!-- no translation found for recentCalls_empty (247053222448663107) -->
+ <skip />
+ <string name="clearCallLogConfirmation_title" msgid="718072843006222703">"የጥሪ ማስታወሻ አጥራ"</string>
+ <string name="clearCallLogConfirmation" msgid="7625927669136267636">"የጥሪ ማስታወሻውን ለማጥራት በእርግጥ ይፈልጋሉ?"</string>
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
+ <!-- no translation found for imei (3045126336951684285) -->
+ <skip />
+ <string name="meid" msgid="6210568493746275750">"MEID"</string>
+ <!-- no translation found for voicemail (3851469869202611441) -->
+ <skip />
+ <!-- no translation found for unknown (740067747858270469) -->
+ <skip />
+ <!-- no translation found for private_num (6374339738119166953) -->
+ <skip />
+ <string name="payphone" msgid="4864313342828942922">"የክፍያ ስልክ"</string>
+ <!-- no translation found for dialerKeyboardHintText (5401660096579787344) -->
+ <skip />
+ <string name="dialerDialpadHintText" msgid="5824490365898349041">"ጥሪ ለማከል ደውል"</string>
+ <!-- no translation found for simContacts_emptyLoading (6700035985448642408) -->
+ <skip />
+ <!-- no translation found for simContacts_title (27341688347689769) -->
+ <skip />
+ <string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"ለማሳየት ምንም እውቂያዎች የልዎትም። (መለያ አሁን ገና ካከሉ፣ እውቂያዎችን ለማሳመር ትንሽ ደቂቃ ሊወስድ ይችላል።)"</string>
+ <string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">" ለማሳየት ምንም እውቂያዎች የልዎትም።"</string>
+ <!-- outdated translation 7633826236417884130 --> <string name="noContactsHelpText" product="tablet" msgid="6450346791169710787">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር በስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት "\n</li></string>
+ <string name="noContactsHelpText" product="default" msgid="7633826236417884130">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር በስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት "\n</li></string>
+ <!-- outdated translation 3017521127042216243 --> <string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።(መለያ ካከሉ፣ዕውቂያዎችን ለማሳመር ጥቂት ደቂቃዎች ይፈጃል።)"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አማራጮች"</b></font>"የትኞቹ ዕውቂያዎች እንደሚታዩ ለመለወጥ አሳይ"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት "\n</li></string>
+ <string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።(መለያ ካከሉ፣ዕውቂያዎችን ለማሳመር ጥቂት ደቂቃዎች ይፈጃል።)"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አማራጮች"</b></font>"የትኞቹ ዕውቂያዎች እንደሚታዩ ለመለወጥ አሳይ"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት "\n</li></string>
+ <!-- outdated translation 467658807711582876 --> <string name="noContactsNoSimHelpText" product="tablet" msgid="6031363021287849874">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት"\n</li></string>
+ <string name="noContactsNoSimHelpText" product="default" msgid="467658807711582876">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት"\n</li></string>
+ <!-- outdated translation 9040060730467973050 --> <string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።(መለያ ካከሉ፣ዕውቂያዎችን ለማሳመር ጥቂት ደቂቃዎች ይፈጃል።)"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አማራጮች"</b></font>"የትኞቹ ዕውቂያዎች እንደሚታዩ ለመለወጥ አሳይ"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት"\n</li></string>
+ <string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"ለማሳየት ምንም ዕውቂያዎች የልዎትም።(መለያ ካከሉ፣ዕውቂያዎችን ለማሳመር ጥቂት ደቂቃዎች ይፈጃል።)"\n\n"ዕውቂያዎች ለማከል፣"<font fgcolor="#ffffffff"><b>"ምናሌ ይጫኑ"</b></font>"እና"\n\n<li><font fgcolor="#ffffffff"><b>"መለያዎች"</b></font>"ለማከል ወይም መለያዎችን ከዕውቂያዎች ጋር ለማወቃር ወደ ስልኩ ማሳመር ይችላሉ፡ይንኩ።"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አማራጮች"</b></font>"የትኞቹ ዕውቂያዎች እንደሚታዩ ለመለወጥ አሳይ"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አዲስ ዕውቂያ"</b></font>"አዲስ ዕውቂያ ከባዶ ለመፍጠር"\n</li>\n<li><font fgcolor="#ffffffff"><b>"አስገባ/ላክ"</b></font>"ከSIM ወይም SD ካርድ ዕውቂያዎች ለማስገባት"\n</li></string>
+ <string name="noFavoritesHelpText" msgid="3744655776704833277">"ምንም ተፈላጊዎች ምርጫ የልዎትም። "\n\n"ዕውቂያዎችዎን ወደ ተፈላጊ ዝርዝር ውስጥ ለማከል፡"\n\n<li>" የዕውቂያዎች"<b>" ትር"</b>" ይንኩ"\n</li>\n<li>" ወደ ተፈላጊዎች ምርጫ ለማከል የፈለጉትን ዕውቂያ ይንኩ"\n</li>\n<li>" ከዕውቂያ ዎች ስም ቀጥሎ ያለውን ኮከብ ይንኩ"\n</li></string>
+ <string name="liveFolder_all_label" msgid="5961411940473276616">"ሁሉም እውቅያዎች"</string>
+ <string name="liveFolder_favorites_label" msgid="2674341514070517105">"ኮከብ የተደረገባቸው"</string>
+ <string name="liveFolder_phones_label" msgid="1709786878793436245">"ስልኮች"</string>
+ <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"የድምፅ ቁልፍ ሰሌዳን ንካ"</string>
+ <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"በመካሄድ ላይ ወዳለው ጥሪ ተመለስ"</string>
+ <string name="dialer_addAnotherCall" msgid="4205688819890074468">"ጥሪ ያክሉ"</string>
+ <string name="callDetailTitle" msgid="5340227785196217938">"የጥሪ ዝርዝሮች"</string>
+ <string name="toast_call_detail_error" msgid="7200975244804730096">"ለተጠየቀው ጥሪዝርዝሮችንማንበብ አልተቻለም።"</string>
+ <string name="type_incoming" msgid="6502076603836088532">"ገቢ ጥሪ"</string>
+ <string name="type_outgoing" msgid="343108709599392641">"ወጪ ጥሪ"</string>
+ <string name="type_missed" msgid="2720502601640509542">"ያመለጠ ጥሪ"</string>
+ <string name="actionIncomingCall" msgid="6028930669817038600">"ገቢ ጥሪዎች"</string>
+ <string name="callBack" msgid="5498224409038809224">"የኋላ ጥሪ"</string>
+ <string name="callAgain" msgid="3197312117049874778">"እንደገና ደውል"</string>
+ <string name="returnCall" msgid="8171961914203617813">"ጥሪ መልስ"</string>
+ <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g>ደቂቃዎች <xliff:g id="SECONDS">%s</xliff:g> ሰከንዶች"</string>
+ <string name="favoritesFrquentSeparator" msgid="8107518433381283736">"በተደጋጋሚ የሚገናኙ"</string>
+ <string name="add_contact_dlg_title" msgid="2896685845822146494">"እውቅያዎች አክል"</string>
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"<xliff:g id="EMAIL">%s</xliff:g> ወደ እውቅያዎች ዝርዝር ይታከል"</string>
+ <string name="description_image_button_one" msgid="1740638037139856139">"አንድ"</string>
+ <string name="description_image_button_two" msgid="5882638439003731308">"ሁለት"</string>
+ <string name="description_image_button_three" msgid="8709731759376015180">"ሦስት"</string>
+ <string name="description_image_button_four" msgid="3530239685642246130">"አራት"</string>
+ <string name="description_image_button_five" msgid="1182465427501188413">"አምስት"</string>
+ <string name="description_image_button_six" msgid="2093656269261415475">"ስድስት"</string>
+ <string name="description_image_button_seven" msgid="2450357020447676481">"ሰባት"</string>
+ <string name="description_image_button_eight" msgid="6969435115163287801">"ስምንት"</string>
+ <string name="description_image_button_nine" msgid="7857248695662558323">"ዘጠኝ"</string>
+ <string name="description_image_button_star" msgid="3365919907520767866">"ኮከብ"</string>
+ <string name="description_image_button_zero" msgid="4133108949401820710">"ዜሮ"</string>
+ <string name="description_image_button_pound" msgid="3039765597595889230">"ፓውንድ"</string>
+ <string name="description_voicemail_button" msgid="3402506823655455591">"የድምፅ መልዕክት"</string>
+ <string name="description_dial_button" msgid="1274091017188142646">"ደውል"</string>
+ <string name="description_delete_button" msgid="6263102114033407382">"የኋሊት ደምሳሽ"</string>
+ <string name="description_digits_edittext" msgid="8760207516497016437">"ቁጥር ለመደወል"</string>
+ <string name="description_contact_photo" msgid="3387458082667894062">"የዕውቂያ ፎቶ"</string>
+ <string name="description_minus_button" msgid="387136707700230172">"ሲቀነስ"</string>
+ <string name="description_plus_button" msgid="515164827856229880">"ተጨማሪ"</string>
+ <!-- outdated translation 5911758680339949273 --> <string name="no_sdcard_title" product="nosdcard" msgid="8543619259870877473">"ምንምSD ካርድ የለም"</string>
+ <string name="no_sdcard_title" product="default" msgid="5911758680339949273">"ምንምSD ካርድ የለም"</string>
+ <!-- outdated translation 6019391476490445358 --> <string name="no_sdcard_message" product="nosdcard" msgid="1334170151822669976">"ምንም SD ካርድ አልተገኘም"</string>
+ <string name="no_sdcard_message" product="default" msgid="6019391476490445358">"ምንም SD ካርድ አልተገኘም"</string>
+ <string name="searching_vcard_title" msgid="4970508055399376813">"vCard ፍለጋ"</string>
+ <string name="import_from_sim" msgid="3859272228033941659">"ከSIM ካርድ አስመጣ"</string>
+ <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"ከSD ካርድአስመጣ"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"ከSD ካርድአስመጣ"</string>
+ <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"ወደ SD ካርድ ላክ"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"ወደ SD ካርድ ላክ"</string>
+ <string name="share_visible_contacts" msgid="890150378880783797">"የሚታዩ እውቂያዎችን አጋራ"</string>
+ <string name="import_one_vcard_string" msgid="9059163467020328433">"አንድ vCard ፋይል አስመጣ"</string>
+ <string name="import_multiple_vcard_string" msgid="3810226492811062392">"ብዙ vCard ፋይሎች አስመጣ"</string>
+ <string name="import_all_vcard_string" msgid="5518136113853448474">"ሁሉም vCard ፋይሎችን አስገባ"</string>
+ <!-- outdated translation 6917522333561434546 --> <string name="searching_vcard_message" product="nosdcard" msgid="996170203695743981">"በSD ካርድ ላይ vCard ፍለጋ"</string>
+ <string name="searching_vcard_message" product="default" msgid="6917522333561434546">"በSD ካርድ ላይ vCard ፍለጋ"</string>
+ <!-- outdated translation 3506782007953167180 --> <string name="scanning_sdcard_failed_title" product="nosdcard" msgid="6957414493948497249">"የSD ካርድ መቃኘትአልተሳካም"</string>
+ <string name="scanning_sdcard_failed_title" product="default" msgid="3506782007953167180">"የSD ካርድ መቃኘትአልተሳካም"</string>
+ <!-- no translation found for scanning_sdcard_failed_message (4106156155205860626) -->
+ <skip />
+ <string name="scanning_sdcard_failed_message" product="default" msgid="3761992500690182922">"የSD ካርድ መቃኘትአልተሳካም (ምክንያት፡\"<xliff:g id="FAIL_REASON">%s</xliff:g>\" )"</string>
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"I/O ስህተት"</string>
+ <string name="fail_reason_low_memory_during_import" msgid="7514918659342886381">"ማህደረ ትውስታ በቂ አይደለም(ፋይሉ ምናልባት በጣም ትልቅ ይሆናል)"</string>
+ <string name="fail_reason_vcard_parse_error" msgid="1201233722762680214">"ባልታወቀ ምክንያትወደ vCard ለመተንተን አልተሳካም"</string>
+ <!-- no translation found for fail_reason_not_supported (294499264620201243) -->
+ <skip />
+ <!-- no translation found for vcard_import_failed (7718330063493653085) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (6339234836196984924) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (1730986357514922756) -->
+ <skip />
+ <string name="fail_reason_failed_to_collect_vcard_meta_info" msgid="4154492282316067754">"የvCard ፋይል(ኦች) ልዕለ መረጃ ለመሰብሰብ አልተሳካም"</string>
+ <string name="fail_reason_failed_to_read_files" msgid="3659521123567134029">"ለማስገባት(%s) አንድ ወይም ተጨማሪ ፋይሎች አልተሳኩም።"</string>
+ <string name="fail_reason_unknown" msgid="999034019513096768">"ያልታወቀ ስህተት"</string>
+ <string name="select_vcard_title" msgid="3968948173786172468">"vCard ፋይል ምረጥ"</string>
+ <string name="caching_vcard_title" msgid="5009556022082659780">"ወደ ጊዜያዊ ማከማቻ vCard(s) መሸጎጫ"</string>
+ <string name="caching_vcard_message" msgid="2380844718093378900">"አስመጪ ወደ ጊዜያዊ ማከማቻ vCard(s) እየሸጎጠ ነው። ትክክለኛው አስመጣ በቅርቡ ይጀምራል።"</string>
+ <string name="progress_notifier_message" msgid="2311011466908220528">"በማስገባት ላይ<xliff:g id="CURRENT_NUMBER">%s</xliff:g>/<xliff:g id="TOTAL_NUMBER">%s</xliff:g>፡<xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="importing_vcard_description" msgid="4245275224298571351">"<xliff:g id="NAME">%s</xliff:g> ማስገባት"</string>
+ <string name="reading_vcard_failed_title" msgid="2162610359561887043">"የvCard ውሂብ ለማንበብ አልተሳካም"</string>
+ <string name="reading_vcard_canceled_title" msgid="1770608329958463131">"የvCard ውሂብ ማንበብ ተሰርዟል"</string>
+ <!-- no translation found for importing_vcard_finished_title (3341541727268747967) -->
+ <skip />
+ <!-- no translation found for importing_vcard_canceled_title (6367906965439777280) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message (2804911199145873396) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message_with_default_name (1022969530654129470) -->
+ <skip />
+ <!-- no translation found for vcard_import_request_rejected_message (2592424820635325951) -->
+ <skip />
+ <!-- no translation found for vcard_export_will_start_message (2210241345252081463) -->
+ <skip />
+ <!-- no translation found for vcard_export_request_rejected_message (8259494002258326330) -->
+ <skip />
+ <!-- no translation found for vcard_unknown_filename (7171709890959915954) -->
+ <skip />
+ <string name="percentage" msgid="34897865327092209">"%s%%"</string>
+ <string name="confirm_export_title" msgid="7648747763127442983">"ላክ አረጋግጥ"</string>
+ <string name="confirm_export_message" msgid="3875683519257829750">"የዕውቂያዝርዝርወደ\"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\" ለመላክ እርግጠኛ ነዎት ይፈልጋሉ?"</string>
+ <string name="exporting_contact_failed_title" msgid="585823094820602526">"የዕውቂያ ውሂብ ለመላክ አለተሳማካም"</string>
+ <string name="exporting_contact_failed_message" msgid="4151348002470298092">"የዕውቂያ ውሂብ ለላክአልተሳካም"\n"ለመታወኩ ምክንያት\"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_no_exportable_contact" msgid="4919714086648344495">"ምንም መላክ የሚችል ዕውቂያ የለም"</string>
+ <!-- outdated translation 7084146295639672658 --> <string name="fail_reason_too_many_vcard" product="nosdcard" msgid="3745507837635270265">"በSD ካርድ ላይ በጣም ብዙ vCard ፋይሎች"</string>
+ <string name="fail_reason_too_many_vcard" product="default" msgid="7084146295639672658">"በSD ካርድ ላይ በጣም ብዙ vCard ፋይሎች"</string>
+ <string name="fail_reason_too_long_filename" msgid="1915716071321839166">"የተጠየቀው ፋይል ስም በጣም ረጅም ነው (\"<xliff:g id="FILENAME">%s</xliff:g>\")"</string>
+ <!-- no translation found for exporting_vcard_finished_title (4259736138838583213) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_canceled_title (1827672399438062140) -->
+ <skip />
+ <string name="exporting_contact_list_title" msgid="9072240631534457415">"የዕውቂያ ውሂብ በመላክ ላይ"</string>
+ <string name="exporting_contact_list_message" msgid="5640326540405486055">"የዕውቂያ ውሂብ ወደ \"<xliff:g id="FILE_NAME">%s</xliff:g>\" በመላክ ላይ"</string>
+ <string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">" ላኪው፡\"<xliff:g id="EXACT_REASON">%s</xliff:g>\" ለማስነሳት አልተቻለም"</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"በላክ ጊዜ <xliff:g id="EXACT_REASON">%s</xliff:g> ስህተት ተከስቷል"</string>
+ <string name="composer_failed_to_get_database_infomation" msgid="3723109558155169053">"የውሂብ ጎታ መረጃ ለማግኘት አልተሳካም"</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="tablet" msgid="5161491059051198932">"መላክ የሚችል ዕውቂያ የለም። በእርግጥ ስልክዎ ላይ ዕውቂያዎች ካልዎ፣ በአንዳንድ የውሂብ አቅራቢዎች ሁሉም ዕውቂያዎች ወደ ውጭ እንዳይላኩ ሊከለክሉ ይችላሉ።"</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="default" msgid="322344221706924358">"መላክ የሚችል ዕውቂያ የለም። በእርግጥ ስልክዎ ላይ ዕውቂያዎች ካልዎ፣ በአንዳንድ የውሂብ አቅራቢዎች ሁሉም ዕውቂያዎች ወደ ውጭ እንዳይላኩ ሊከለክሉ ይችላሉ።"</string>
+ <string name="composer_not_initialized" msgid="8041534450748388843">"የvCard ፅሁፍ አዘጋጅ በትክክል አልተነሳም።"</string>
+ <string name="fail_reason_could_not_open_file" msgid="4013520943128739511">" \"<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> ከ <xliff:g id="TOTAL_NUMBER">%s</xliff:g> እውቂያዎች"</string>
+ <!-- no translation found for cancel_import_confirmation_title (5578683596010294836) -->
+ <skip />
+ <!-- no translation found for cancel_import_confirmation_message (8560937090143057107) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_title (6516467140276768528) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_message (1392976902396351957) -->
+ <skip />
+ <!-- no translation found for cancel_vcard_import_or_export_failed (7096533244663846810) -->
+ <skip />
+ <string name="search_settings_description" msgid="2675223022992445813">"የዕውቂያዎችዎ ስሞች"</string>
+ <string name="add_2sec_pause" msgid="9214012315201040129">"2 ሰከንድ ፋታ አክል"</string>
+ <string name="add_wait" msgid="3360818652790319634">"ጠብቅአክል"</string>
+ <string name="call_disambig_title" msgid="1911302597959335178">"ጥሪ በመጠቀም"</string>
+ <string name="sms_disambig_title" msgid="4675399294513152364">"ፅሁፍበመጠቀም"</string>
+ <string name="make_primary" msgid="5829291915305113983">"ይህን ምርጫ አስታውስ"</string>
+ <string name="quickcontact_missing_app" msgid="4600366393134289038">"ይህን እርምጃ ለማስተናገድ ምንም ትግበራ አልተገኘም"</string>
+ <string name="quickcontact_remember_choice" msgid="5964536411579749424">"ይህን ምርጫ አስታውስ"</string>
+ <string name="quickcontact_missing_name" msgid="5590266114306996632">"ያልታወቀ"</string>
+ <string name="quickcontact_no_data" msgid="2098000859125253675">"ምንም ውሂብ"</string>
+ <!-- no translation found for quickcontact_clear_defaults_description (3792792870662989100) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_caption (4287306111861545753) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_button (8728754360205289059) -->
+ <skip />
+ <string name="menu_accounts" msgid="8499114602017077970">"መለያዎች"</string>
+ <string name="menu_import_export" msgid="3765725645491577190">"አስመጣ/ላክ"</string>
+ <string name="dialog_import_export" msgid="4771877268244096596">"ዕውቂያዎች አስመጣ/ላክ"</string>
+ <!-- outdated translation 943789700636542260 --> <string name="menu_share" msgid="8746849630474240344">"መጋሪያ"</string>
+ <string name="share_via" msgid="563121028023030093">"ዕውቂያበ በኩል አጋራ"</string>
+ <string name="share_error" msgid="4374508848981697170">"ይህ ዕውቂያ መጋራት አይችልም።"</string>
+ <string name="nameLabelsGroup" msgid="2034640839640477827">"ስም"</string>
+ <string name="nicknameLabelsGroup" msgid="2891682101053358010">"ቅጽል ስም"</string>
+ <string name="organizationLabelsGroup" msgid="2478611760751832035">"መስርያ ቤት"</string>
+ <string name="websiteLabelsGroup" msgid="4202998982804009261">"ድረ ገፅ"</string>
+ <string name="eventLabelsGroup" msgid="8069912895912714412">"ዝግጅት"</string>
+ <!-- no translation found for relationLabelsGroup (1854373894284572781) -->
+ <skip />
+ <string name="groupsLabel" msgid="8573535366319059326">"ቡድኖች"</string>
+ <string name="type_short_home" msgid="7770424864090605384">"H"</string>
+ <string name="type_short_mobile" msgid="1655473281466676216">"M"</string>
+ <string name="type_short_work" msgid="4925330752504537861">"W"</string>
+ <string name="type_short_pager" msgid="2613818970827594238">"P"</string>
+ <string name="type_short_other" msgid="5669407180177236769">"O"</string>
+ <string name="dialog_new_contact_account" msgid="9044704073286262197">"በመለያ ስር ዕውቂያ ፍጠር"</string>
+ <string name="menu_sync_remove" msgid="3266725887008450161">"የአሳምር ቡድን አስወግድ"</string>
+ <string name="dialog_sync_add" msgid="8267045393119375803">"አሳምርቡድንአክል"</string>
+ <string name="display_more_groups" msgid="2682547080423434170">"ተጨማሪቡድኖች..."</string>
+ <string name="display_ungrouped" msgid="4602580795576261158">"ሌላሁሉም ዕውቂያዎች"</string>
+ <string name="display_all_contacts" msgid="6846131371214707956">"ሁሉም እውቅያዎች"</string>
+ <string name="display_warn_remove_ungrouped" msgid="2314043155909167610">"\'<xliff:g id="GROUP">%s</xliff:g>\' ከአሳምር ማስወገድ እንዲሁ ማንኛውም በተነጣጥል ያሉ ዕውቆችን ከአሳምር ያስወግዳል።"</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="tablet" msgid="7946049152658522054">"ስልክ- ብቻ(ያልሰመረ)"</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="default" msgid="3682950835276226870">"ስልክ- ብቻ(ያልሰመረ)"</string>
+ <string name="call_custom" msgid="7756571794763171802">"ጥሪ <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="call_home" msgid="1990519474420545392">" መነሻጥሪ"</string>
+ <string name="call_mobile" msgid="7502236805487609178">"ተንቀሳቃሽ ስልክ ጥሪ"</string>
+ <string name="call_work" msgid="5328785911463744028">"የሥራ ጥሪ"</string>
+ <string name="call_fax_work" msgid="7467763592359059243">"የሥራ ጥሪ ፋክስ"</string>
+ <string name="call_fax_home" msgid="8342175628887571876">"የጥሪ መነሻፋክስ"</string>
+ <string name="call_pager" msgid="9003902812293983281">"ምልክት ማድረጊያ ጥሪ"</string>
+ <string name="call_other" msgid="8563753966926932052">"ደውል"</string>
+ <string name="call_callback" msgid="1910165691349426858">"ተዘዋዋሪ ጥሪ ደውል"</string>
+ <string name="call_car" msgid="3280537320306436445">"የመኪና ደውል"</string>
+ <string name="call_company_main" msgid="6105120947138711257">"የጥሪ ኩባንያ ዋና"</string>
+ <string name="call_isdn" msgid="1541590690193403411">"ISDN ጥሪ"</string>
+ <string name="call_main" msgid="6082900571803441339">"ዋና ጥሪ"</string>
+ <string name="call_other_fax" msgid="5745314124619636674">"ፋክስ ደውል"</string>
+ <string name="call_radio" msgid="8296755876398357063">"የሬዲዮጥሪ"</string>
+ <string name="call_telex" msgid="2223170774548648114">"ቴሌክስጥሪ"</string>
+ <string name="call_tty_tdd" msgid="8951266948204379604">"TTY/TDD ጥሪ"</string>
+ <string name="call_work_mobile" msgid="8707874281430105394">"ተንቀሳቃሽ ሥራ ስልክደውል"</string>
+ <string name="call_work_pager" msgid="3419348514157949008">"የሥራ ጥሪ ምልክት ማድረጊያ"</string>
+ <string name="call_assistant" msgid="2141641383068514308">"ጥሪ <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="call_mms" msgid="6274041545876221437">"MMS ጥሪ"</string>
+ <string name="sms_custom" msgid="5932736853732191825">"ፅሁፍ <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="sms_home" msgid="7524332261493162995">"የፅሁፍመነሻ"</string>
+ <string name="sms_mobile" msgid="5200107250451030769">"የ ተንቀሳቃሽፅሁፍ"</string>
+ <string name="sms_work" msgid="2269624156655267740">"የፅሁፍ ሥራ"</string>
+ <string name="sms_fax_work" msgid="8028189067816907075">"የፅሁፍ ሥራፋክስ"</string>
+ <string name="sms_fax_home" msgid="9204042076306809634">"የመነሻ ፅሁፍ ፋክስ"</string>
+ <string name="sms_pager" msgid="7730404569637015192">"የፅሁፍ ምልክት ማድረጊያ"</string>
+ <string name="sms_other" msgid="806127844607642331">"ፅሁፍ"</string>
+ <string name="sms_callback" msgid="5004824430094288752">"የተዘዋዋሪ ጥሪ ፅሁፍ"</string>
+ <string name="sms_car" msgid="7444227058437359641">"የፅሁፍ ማሽን"</string>
+ <string name="sms_company_main" msgid="118970873419678087">"የኩባንያ ዋናፅሁፍ"</string>
+ <string name="sms_isdn" msgid="8153785037515047845">"የ ISDN ፅሁፍ"</string>
+ <string name="sms_main" msgid="8621625784504541679">"የዋና ፅሁፍ"</string>
+ <string name="sms_other_fax" msgid="3888842199855843152">"የፋክስ ፅሁፍ"</string>
+ <string name="sms_radio" msgid="3329166673433967820">"የፅሁፍ ሬዲዮ"</string>
+ <string name="sms_telex" msgid="9034802430065267848">"የፅሁፍ ቴሌክስ"</string>
+ <string name="sms_tty_tdd" msgid="6782284969132531532">"TTY/TDD ፅሁፍ"</string>
+ <string name="sms_work_mobile" msgid="2459939960512702560">"የፅሁፍ ሥራ ተንቀሳቃሽ"</string>
+ <string name="sms_work_pager" msgid="5566924423316960597">"የፅሁፍ ሥራ ምልክት ማድረጊያ"</string>
+ <string name="sms_assistant" msgid="2773424339923116234">"ፅሁፍ <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="sms_mms" msgid="4069352461380762677">"የMMS ፅሁፍ"</string>
+ <string name="email_home" msgid="8573740658148184279">"የኢሜይል መነሻ"</string>
+ <string name="email_mobile" msgid="2042889209787989814">"ኢሜይል ተንቀሳቃሽ"</string>
+ <string name="email_work" msgid="2807430017302722689">"ኢሜይልሥራ"</string>
+ <string name="email_other" msgid="3454004077967657109">"ኢሜይል"</string>
+ <string name="email_custom" msgid="7548003991586214105">"ኢሜይል <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="email" msgid="5668400997660065897">"ኢሜይል"</string>
+ <string name="map_home" msgid="1243547733423343982">"የመነሻ አድራሻ ዕይ"</string>
+ <string name="map_work" msgid="1360474076921878088">"የሥራ አድራሻ ዕይ"</string>
+ <string name="map_other" msgid="3817820803587012641">"አድራሻ እይ"</string>
+ <string name="map_custom" msgid="6184363799976265281">"<xliff:g id="CUSTOM">%s</xliff:g> አድራሻዎች እይ"</string>
+ <string name="chat_aim" msgid="2588492205291249142">"ጨዋታ AIM በመጠቀም"</string>
+ <string name="chat_msn" msgid="8041633440091073484">"ጨዋታ Windows Live በመጠቀም"</string>
+ <string name="chat_yahoo" msgid="6629211142719943666">"Yahoo ፣ውይይት በመጠቀም"</string>
+ <string name="chat_skype" msgid="1210045020427480566">"ጨዋታ Skype በመጠቀም"</string>
+ <string name="chat_qq" msgid="4294637812847719693">"ጨዋታ QQ በመጠቀም"</string>
+ <string name="chat_gtalk" msgid="981575737258117697">"የGoogle Talk በመጠቀም ጨዋታ"</string>
+ <string name="chat_icq" msgid="8438405386153745775">"ጨዋታ ICQ በመጠቀም"</string>
+ <string name="chat_jabber" msgid="7561444230307829609">"ጨዋታ Jabber በመጠቀም"</string>
+ <string name="chat" msgid="9025361898797412245">"ጨዋታ"</string>
+ <string name="postal_address" msgid="8765560217149624536">"አድራሻ"</string>
+ <string name="postal_street" msgid="8133143961580058972">"ጎዳና"</string>
+ <string name="postal_pobox" msgid="4431938829180269821">"ፖስታ ሣጥን ቁጥር"</string>
+ <string name="postal_neighborhood" msgid="1450783874558956739">"ጎረቤት"</string>
+ <string name="postal_city" msgid="6597491300084895548">"ከተማ፡"</string>
+ <string name="postal_region" msgid="6045263193478437672">"ክልል፡"</string>
+ <string name="postal_postcode" msgid="572136414136673751">"ዚፕ ኮድ"</string>
+ <string name="postal_country" msgid="7638264508416368690">"አገር፡"</string>
+ <string name="full_name" msgid="6602579550613988977">"ስም"</string>
+ <string name="name_given" msgid="1687286314106019813">"የተሰጠ ስም"</string>
+ <string name="name_family" msgid="3416695586119999058">"የቤተሰብ ስም"</string>
+ <string name="name_prefix" msgid="59756378548779822">"ቅድመ ስም"</string>
+ <string name="name_middle" msgid="8467433655992690326">"የአባት ስም"</string>
+ <string name="name_suffix" msgid="3855278445375651441">"ድህረ ስም"</string>
+ <string name="name_phonetic_given" msgid="6853570431394449191">"በድምፀ ልሳን የተሰጠ ስም"</string>
+ <string name="name_phonetic_middle" msgid="8643721493320405200">"የድምፀ ልሳንመካከለኛ ስም"</string>
+ <string name="name_phonetic_family" msgid="462095502140180305">"የድምፀ ልሳን ቤተሰብ ስም"</string>
+ <!-- no translation found for name_phonetic (4259595234312430484) -->
+ <skip />
+ <string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> እውቅያ"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
+ <string name="use_photo_as_primary" msgid="8807110122951157246">"ይህን ፎቶ ተጠቀም"</string>
+ <string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g>የዕውቂያ መረጃ በዚህ መሣሪያ ላይ አርትዕ መደረግ የሚቻል አይደለም።"</string>
+ <string name="no_contact_details" msgid="6754415338321837001">"ለዚህ ዕውቂያ ምንም ተጨማሪ መረጃ የለም"</string>
+ <string name="display_options_sort_list_by" msgid="6080091755852211076">"ዝርዝር በ ለይ"</string>
+ <string name="display_options_sort_by_given_name" msgid="184916793466387067">"መጠሪያ ስም"</string>
+ <string name="display_options_sort_by_family_name" msgid="7857986975275712622">"የቤተሰብ ስም"</string>
+ <string name="display_options_view_names_as" msgid="18022868169627979">"የእውቂያ ስሞችን እንደ እይ"</string>
+ <string name="display_options_view_given_name_first" msgid="6968288511197363292">"መጠሪያ ስም መጀመሪያ"</string>
+ <string name="display_options_view_family_name_first" msgid="1447288164951453714">"የቤተሰብ መነሻስም"</string>
+ <string name="search_bar_hint" msgid="1012756309632856553">"እውቅያዎችዎን ይፈልጉ"</string>
+ <string name="search_for_all_contacts" msgid="6644963335787294131">"ለሁሉም እውቂያዎች ፈልግ"</string>
+ <string name="take_photo" msgid="7496128293167402354">"ፎቶ አንሳ"</string>
+ <!-- no translation found for take_new_photo (7341354729436576304) -->
+ <skip />
+ <string name="pick_photo" msgid="448886509158039462">"ፎቶ ከሥነ ጥበብ ማዕከል ምረጥ"</string>
+ <!-- no translation found for pick_new_photo (7962368009197147617) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in locale_change_in_progress -->
+ <skip />
+ <!-- no translation found for locale_change_in_progress (7583992153091537467) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in upgrade_in_progress -->
+ <skip />
+ <!-- no translation found for upgrade_in_progress (474511436863451061) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory (6153384328042175667) -->
+ <skip />
+ <string name="upgrade_out_of_memory_uninstall" msgid="1721798828992091432">"አንዳንድ ትግበራዎችን አለመጫን"</string>
+ <string name="upgrade_out_of_memory_retry" msgid="8431289830472724609">"አልቅ ድጋሚ ሞክር"</string>
+ <string name="search_results_searching" msgid="7755623475227227314">"በመፈለግ ላይ..."</string>
+ <string name="menu_display_selected" msgid="6470001164297969034">"የተመረጡትን አሳይ"</string>
+ <string name="menu_display_all" msgid="8887488642609786198">"ሁሉንም አሳይ"</string>
+ <string name="menu_select_all" msgid="621719255150713545">"ሁሉንም ምረጥ"</string>
+ <string name="menu_select_none" msgid="7093222469852132345">"ሁሉንም አትምረጥ"</string>
+ <plurals name="multiple_picker_title">
+ <item quantity="one" msgid="4761009734586319101">"1 ተቀባይ ተመርጧል"</item>
+ <item quantity="other" msgid="4608837420986126229">"<xliff:g id="COUNT">%d</xliff:g> ተቀባዮች ተመርጠዋል"</item>
+ </plurals>
+ <string name="no_contacts_selected" msgid="5877803471037324613">"ምንም እውቂያዎች አልተመረጡም."</string>
+ <!-- no translation found for add_field (2384260056674995230) -->
+ <skip />
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
+ <string name="contact_status_update_attribution" msgid="752179367353018597">"በ<xliff:g id="SOURCE">%1$s</xliff:g> በኩል"</string>
+ <string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>በ<xliff:g id="SOURCE">%2$s</xliff:g> በኩል"</string>
+ <string name="description_star" msgid="2605854427360036550">"ተወዳጅ"</string>
+ <string name="edit_contact" msgid="7529281274005689512">"እውቅያ አርትእ"</string>
+ <plurals name="merge_info">
+ <item quantity="one" msgid="148365587896371969">"አልተዋሃደም"</item>
+ <item quantity="other" msgid="425683718017380845">"ከ<xliff:g id="COUNT">%0$d</xliff:g> ምንጮች የተዋሃደ"</item>
+ </plurals>
+ <string name="local_invisible_directory" msgid="6046691709127661065">"ሌላ"</string>
+ <!-- no translation found for aggregation_suggestion_join_dialog_title (5276699501316246253) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_message (3842757977671434836) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_title (1064042382692091314) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_message (6549585283910518095) -->
+ <skip />
+ <string name="menu_copyContact" msgid="4401683725471696686">"ወደ ዕውቂያዎቼ ቅዳ"</string>
+ <!-- no translation found for contact_directory_description (683398073603909119) -->
+ <skip />
+ <!-- no translation found for search_label (6789295859496641042) -->
+ <skip />
+ <string name="directory_search_label" msgid="1887759056597975053">" ማውጫ"</string>
+ <string name="local_search_label" msgid="1686089693064201315">"እውቅያዎች"</string>
+ <string name="toast_making_personal_copy" msgid="7905283986345263275">"የግል ቅጂ መፍጠር"</string>
+ <string name="list_filter_prompt" msgid="7481426622828055116">"ዕውቂያ ዝርዝር ምረጥ"</string>
+ <string name="list_filter_all_accounts" msgid="8908683398914322369">"ሁሉም እውቅያዎች"</string>
+ <!-- no translation found for list_filter_all_starred (5031734941601931356) -->
+ <skip />
+ <!-- no translation found for list_filter_custom (8910173055702057002) -->
+ <skip />
+ <string name="list_filter_customize" msgid="2035084418635775579">"አብጅ..."</string>
+ <!-- no translation found for list_filter_phones (7905045603593508221) -->
+ <skip />
+ <!-- no translation found for list_filter_single (5871400283515893087) -->
+ <skip />
+ <!-- no translation found for custom_list_filter (7836035257402013957) -->
+ <skip />
+ <string name="activity_title_settings" msgid="5464130076132770781">"ቅንብሮች"</string>
+ <string name="menu_settings" msgid="377929915873428211">"ቅንብሮች"</string>
+ <string name="preference_displayOptions" msgid="1341720270148252393">"ማሳያ አማራጮች"</string>
+ <!-- no translation found for organization_company_and_title (6718207751363732025) -->
+ <skip />
+ <!-- no translation found for hint_findContacts (1808681193458772072) -->
+ <skip />
+ <!-- no translation found for non_phone_caption (1541655052330027380) -->
+ <skip />
+ <!-- no translation found for non_phone_add_to_contacts (6590985286250471169) -->
+ <skip />
+ <!-- no translation found for non_phone_close (7608506439725515667) -->
+ <skip />
+ <!-- no translation found for widget_name_and_phonetic (8739586586600099979) -->
+ <skip />
+ <!-- no translation found for date_year_toggle (7356532842767854606) -->
+ <skip />
+ <!-- no translation found for social_widget_label (6378905543028924592) -->
+ <skip />
+ <!-- no translation found for social_widget_loading (3697996166985327861) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_create_contact (7014525713871959208) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_add_account (7911101713860139754) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_import_contacts (4456440183590517471) -->
+ <skip />
+ <!-- no translation found for create_group_dialog_title (6874527142828424475) -->
+ <skip />
+ <!-- no translation found for create_group_item_label (5218022006186243310) -->
+ <skip />
+ <!-- no translation found for rename_group_dialog_title (3765299704290513289) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_title (7368429698398624427) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_message (295063284548750881) -->
+ <skip />
+ <!-- no translation found for toast_join_with_empty_contact (5015189525953438968) -->
+ <skip />
+ <!-- no translation found for indicator_joined_contact (3321049349627022128) -->
+ <skip />
+ <!-- no translation found for toast_text_copied (5143776250008541719) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_title (3950463632415908534) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_message (7021968394611740251) -->
+ <skip />
+ <!-- no translation found for discard (1234315037371251414) -->
+ <skip />
+</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index da08594..885ca51 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"افتراضي"</string>
<string name="removePhoto" msgid="4898105274130284565">"إزالة الصور"</string>
<string name="noContacts" msgid="8579310973261953559">"لا توجد جهات اتصال."</string>
+ <string name="noGroups" msgid="8614664663561385253">"لا توجد مجموعات."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"لم يتم العثور على أية جهات اتصال متطابقة."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"ليس هناك جهات اتصال تشتمل على أرقام هواتف."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"جهات الاتصال فقط التي بها صور"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"تم العثور على <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"جهات الاتصال"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"المجموعات"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"المفضلة"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"الهاتف"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"سجل المكالمات"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"سجل المكالمات فارغ."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"محو سجل المكالمات"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"هل أنت متأكد من أنك تريد محو سجل المكالمات؟"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"جارٍ محو سجل المكالمات"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"البريد الصوتي"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"لم يتم اكتشاف بطاقة SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"البحث عن vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"استيراد من بطاقة SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"استيراد من وحدة التخزين"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"تصدير إلى وحدة التخزين"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"استيراد من وحدة التخزين"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"استيراد من بطاقة SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"تصدير إلى وحدة التخزين"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"تصدير إلى بطاقة SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"مشاركة جهات الاتصال المرئية"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"استيراد ملف vCard واحد"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"استيراد ملفات vCard متعددة"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"اسم الأسرة الصوتي"</string>
<string name="name_phonetic" msgid="4259595234312430484">"الاسم"</string>
<string name="account_type_format" msgid="718948015590343010">"جهة اتصال <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"من <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"استخدام هذه الصورة"</string>
<string name="contact_read_only" msgid="1203216914575723978">"معلومات جهة اتصال <xliff:g id="SOURCE">%1$s</xliff:g> غير قابلة للتعديل على هذا الجهاز."</string>
<string name="no_contact_details" msgid="6754415338321837001">"ليس هناك معلومات إضافية لجهة الاتصال هذه"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"لم يتم تحديد جهات اتصال."</string>
<string name="add_field" msgid="2384260056674995230">"إضافة حقل آخر"</string>
+ <string name="add_phone" msgid="4421904942555210013">"إضافة رقم هاتف جديد"</string>
+ <string name="add_email" msgid="175079666329862215">"إضافة بريد إلكتروني جديد"</string>
+ <string name="add_im" msgid="5158094627521120439">"إضافة حساب مراسلة فورية جديد"</string>
+ <string name="add_address" msgid="418292312672970688">"إضافة عنوان جديد"</string>
+ <string name="add_note" msgid="2753771325725383279">"إضافة ملاحظة جديدة"</string>
+ <string name="add_website" msgid="4312391288948517344">"إضافة موقع إلكتروني جديد"</string>
+ <string name="add_event" msgid="7488781591843886426">"إضافة حدث جديد"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"إضافة علاقة جديدة"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"عبر <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> عبر <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"مفضل"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 4466bbe..f3d761b 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"По подразбиране"</string>
<string name="removePhoto" msgid="4898105274130284565">"Премахване на снимката"</string>
<string name="noContacts" msgid="8579310973261953559">"Няма контакти."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Няма групи."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Не са намерени съответстващи контакти."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Няма контакти с тел. номера."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Само контакти с тел. номера"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> намерени"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Контакти"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Групи"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Любими"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Телефон"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Списък на обажданията"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Списъкът на обажданията е празен."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Изчистване на списъка с обажданията"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Наистина ли искате да изчистите списъка на обажданията?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Списъкът с обажданията се изчиства"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Гласова поща"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Не е открита SD карта"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Търсене на vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Импортиране от SIM карта"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Импорт. от хранилището"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Експорт. в хранилището"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Импорт. от хранилището"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Импортиране от SD карта"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Експорт. в хранилището"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Експортиране в SD карта"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Споделяне на видимите контакти"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Импортиране на един vCard файл"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Импортиране на няколко vCard файла"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Фамилия, както се произнася"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Име, както се произнася"</string>
<string name="account_type_format" msgid="718948015590343010">"Контакт от <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"от <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Използване на тази снимка"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Информацията за контакта от <xliff:g id="SOURCE">%1$s</xliff:g> не може да бъде редактирана на това устройство."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Няма допълнителна информация за този контакт"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Няма избрани контакти."</string>
<string name="add_field" msgid="2384260056674995230">"Добавяне на друго поле"</string>
+ <string name="add_phone" msgid="4421904942555210013">"+ Нов телефонен номер"</string>
+ <string name="add_email" msgid="175079666329862215">"+ Нов имейл"</string>
+ <string name="add_im" msgid="5158094627521120439">"+ Нов профил за чат"</string>
+ <string name="add_address" msgid="418292312672970688">"+ Нов адрес"</string>
+ <string name="add_note" msgid="2753771325725383279">"+ Нова бележка"</string>
+ <string name="add_website" msgid="4312391288948517344">"+ Нов уебсайт"</string>
+ <string name="add_event" msgid="7488781591843886426">"+ Ново събитие"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"+ Ново взаимоотношение"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"чрез <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> чрез <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"любимо"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index a2aa29d..9d704f2 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predeterminat"</string>
<string name="removePhoto" msgid="4898105274130284565">"Elimina la foto"</string>
<string name="noContacts" msgid="8579310973261953559">"No hi ha contactes."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Cap grup"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"No s\'ha trobat cap contacte coincident."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"No hi ha cap contacte amb número de telèfon."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Només els contactes amb telèfons"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> contactes"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contactes"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grups"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Preferits"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telèfon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Registre de trucades"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"El registre de trucades és buit."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Esborrament del registre de trucades"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Esteu segur que voleu esborrar el registre de trucades?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Esborrant el registre de trucada"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Correu de veu"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"No s\'ha detectat cap targeta SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"S\'està cercant la vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importa des de la targeta SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importa de l\'emmagatzematge"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exporta a emmagatzematge"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importa de l\'emmagatzematge"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importa des de la targeta SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exporta a emmagatzematge"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exporta a la targeta SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Comparteix els contactes visibles"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importa un fitxer vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importa diversos fitxers vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Cognoms fonètics"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nom fonètic"</string>
<string name="account_type_format" msgid="718948015590343010">"Contacte de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilitza aquesta foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"La informació de contacte de <xliff:g id="SOURCE">%1$s</xliff:g> no es pot editar en aquest dispositiu."</string>
<string name="no_contact_details" msgid="6754415338321837001">"No hi ha informació addicional per a aquest contacte"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"No s\'ha seleccionat cap contacte."</string>
<string name="add_field" msgid="2384260056674995230">"Afegeix un altre camp"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Afegeix núm. tel. nou"</string>
+ <string name="add_email" msgid="175079666329862215">"Afegeix correu el. nou"</string>
+ <string name="add_im" msgid="5158094627521120439">"Afegeix compte MI nou"</string>
+ <string name="add_address" msgid="418292312672970688">"Afegeix adreça nova"</string>
+ <string name="add_note" msgid="2753771325725383279">"Afegeix nota nova"</string>
+ <string name="add_website" msgid="4312391288948517344">"Afegeix lloc web nou"</string>
+ <string name="add_event" msgid="7488781591843886426">"Afegeix esdevenim. nou"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Afegeix relació nova"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"mitjançant <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> mitjançant <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"preferit"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index e78c66a..11efc2f 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Výchozí nastavení"</string>
<string name="removePhoto" msgid="4898105274130284565">"Odebrat fotografii"</string>
<string name="noContacts" msgid="8579310973261953559">"Žádné kontakty."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Žádné skupiny."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nebyly nalezeny žádné odpovídající kontakty."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Ke kontaktům nejsou přiřazena žádná telefonní čísla."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Pouze kontakty s telefony"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Počet nalezených položek: <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakty"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Skupiny"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Oblíbené"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Hovory"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Záznam hovorů je prázdný."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Vymazat hovory"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Opravdu chcete vymazat hovory?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Vymazání hovorů"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Hlasová schránka"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nebyla zjištěna žádná karta SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Vyhledávání karty vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importovat z karty SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importovat z úložiště"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportovat do úložiště"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importovat z úložiště"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importovat z karty SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportovat do úložiště"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportovat na kartu SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Sdílet viditelné kontakty"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importovat jeden soubor vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importovat několik souborů vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Příjmení (foneticky)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Jméno (foneticky)"</string>
<string name="account_type_format" msgid="718948015590343010">"Kontakt ze zdroje <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"z účtu <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Použít tuto fotografii"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Kontaktní informace ze zdroje <xliff:g id="SOURCE">%1$s</xliff:g> není možné na tomto zařízení upravit."</string>
<string name="no_contact_details" msgid="6754415338321837001">"U tohoto kontaktu nejsou uvedeny dodatečné informace"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nevybrali jste žádné kontakty."</string>
<string name="add_field" msgid="2384260056674995230">"Přidat další pole"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Přidat nové tel. číslo"</string>
+ <string name="add_email" msgid="175079666329862215">"Přidat nový e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Přidat nový účet IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Přidat novou adresu"</string>
+ <string name="add_note" msgid="2753771325725383279">"Přidat novou poznámku"</string>
+ <string name="add_website" msgid="4312391288948517344">"Přidat nový web"</string>
+ <string name="add_event" msgid="7488781591843886426">"Přidat novou událost"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Přidat nový vztah"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"pomocí služby <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> prostřednictvím služby <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"oblíbené"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index da1b262..6f3f698 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Standard"</string>
<string name="removePhoto" msgid="4898105274130284565">"Fjern billede"</string>
<string name="noContacts" msgid="8579310973261953559">"Der er ingen kontakter."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Ingen grupper."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Der blev ikke fundet nogen matchende kontakter."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Der er ingen kontakter med telefonnumre."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Kun kontakter med telefoner"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> fundet"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakter"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupper"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favorit"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Opk.liste"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Opkaldslisten er tom."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Ryd opkaldsliste"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Er du sikker på, at du vil rydde opkaldslisten?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Rydder opkaldsliste"</string>
<string name="imei" msgid="3045126336951684285">"IMEI-nummer"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Voicemail"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Der blev ikke fundet noget SD-kort"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Søger efter vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importer fra SIM-kort"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importer fra lager"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Eksporter til lager"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importer fra lager"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importer fra SD-kort"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Eksporter til lager"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Eksporter til SD-kort"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Del synlige kontaktpersoner"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importer en VCard-fil"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importer flere VCard-filer"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetisk efternavn"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetisk navn"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kontaktperson"</string>
- <string name="from_account_format" msgid="687567483928582084">"fra<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Brug dette billede"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> kontaktoplysninger kan ikke redigeres på denne enhed."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Ingen yderligere oplysninger for denne kontakt"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Ingen kontaktpersoner er valgt."</string>
<string name="add_field" msgid="2384260056674995230">"Tilføj et felt mere"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Tilføj nyt telefonnr."</string>
+ <string name="add_email" msgid="175079666329862215">"Tilføj ny e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Tilføj ny IM-konto"</string>
+ <string name="add_address" msgid="418292312672970688">"Tilføj ny adresse"</string>
+ <string name="add_note" msgid="2753771325725383279">"Tilføj ny bemærkning"</string>
+ <string name="add_website" msgid="4312391288948517344">"Tilføj nyt websted"</string>
+ <string name="add_event" msgid="7488781591843886426">"Tilføj ny begivenhed"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Tilføj nyt forhold"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"foretrukken"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7411364..2ea0a5a 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Standard"</string>
<string name="removePhoto" msgid="4898105274130284565">"Foto entfernen"</string>
<string name="noContacts" msgid="8579310973261953559">"Keine Kontakte"</string>
+ <string name="noGroups" msgid="8614664663561385253">"Keine Gruppen"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Keine passenden Kontakte gefunden"</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Keine sichtbaren Kontakte mit Telefonnummern"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Nur Kontakte mit Telefon"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> gefunden"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakte"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Gruppen"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoriten"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Anrufe"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Anrufliste ist leer"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Anrufprotokoll löschen"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Möchten Sie das Anrufprotokoll wirklich löschen?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Anrufprotokoll wird gelöscht."</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Mailbox"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Keine SD-Karte gefunden"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCard wird gesucht."</string>
<string name="import_from_sim" msgid="3859272228033941659">"Von SIM-Karte importieren"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Aus Speicher importieren"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"In Speicher exportieren"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Aus Speicher importieren"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Von SD-Karte importieren"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"In Speicher exportieren"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Auf SD-Karte exportieren"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Sichtbare Kontakte weitergeben"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Eine VCard-Datei importieren"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Mehrere VCard-Dateien importieren"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Phonetischer Nachname"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Phonetischer Name"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g>-Kontakt"</string>
- <string name="from_account_format" msgid="687567483928582084">"von <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Dieses Foto verwenden"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g>-Kontaktinformationen können auf diesem Gerät nicht bearbeitet werden."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Keine Zusatzinformationen zu diesem Kontakt"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Kein Kontakt ausgewählt"</string>
<string name="add_field" msgid="2384260056674995230">"Weiteres Feld hinzufügen"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Neue Telefonnummer"</string>
+ <string name="add_email" msgid="175079666329862215">"Neue E-Mail-Adresse"</string>
+ <string name="add_im" msgid="5158094627521120439">"Chat-Konto hinzufügen"</string>
+ <string name="add_address" msgid="418292312672970688">"Adresse hinzufügen"</string>
+ <string name="add_note" msgid="2753771325725383279">"Neue Notiz hinzufügen"</string>
+ <string name="add_website" msgid="4312391288948517344">"Website hinzufügen"</string>
+ <string name="add_event" msgid="7488781591843886426">"Ereignis hinzufügen"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Beziehung hinzufügen"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"über <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> über <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"Favorit"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index e71a339..8ce4e4a 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Προεπιλογή"</string>
<string name="removePhoto" msgid="4898105274130284565">"Κατάργηση εικόνας"</string>
<string name="noContacts" msgid="8579310973261953559">"Δεν υπάρχουν επαφές."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Δεν υπάρχουν ομάδες."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Δεν βρέθηκαν επαφές που να αντιστοιχούν."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Δεν υπάρχουν επαφές με αριθμούς τηλεφώνου."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Μόνο επαφές με τηλέφωνα"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Βρέθηκαν <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Επαφές"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Ομάδες"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Αγαπ."</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Τηλέφωνο"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Αρχείο"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Το αρχείο καταγραφής κλήσεων είναι κενό."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Εκκαθάριση αρχείου καταγραφής κλήσεων"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Είστε βέβαιοι ότι θέλετε να γίνει εκκαθάριση του αρχείου καταγραφής κλήσεων;"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Εκκαθάριση αρχείου καταγρ. κλήσεων"</string>
<string name="imei" msgid="3045126336951684285">"Αριθμός ΙΜΕΙ"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Αυτόματος τηλεφωνητής"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Δεν ανιχνεύθηκε κάρτα SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Αναζήτηση κάρτας vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Εισαγωγή από κάρτα SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Εισαγωγή από τον χώρο αποθ."</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Εξαγωγή στον χώρο αποθ."</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Εισαγωγή από τον χώρο αποθ."</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Εισαγωγή από κάρτα SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Εξαγωγή στον χώρο αποθ."</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Εξαγωγή σε κάρτα SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Κοινή χρήση ορατών επαφών"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Εισαγωγή ενός αρχείου VCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Εισαγωγή πολλαπλών αρχείων vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Φωνητική γραφή επιθέτου"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Όνομα σε φωνητική γραφή"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> επαφή"</string>
- <string name="from_account_format" msgid="687567483928582084">"από <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Χρήση αυτής της φωτογραφίας"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Τα στοιχεία επικοινωνίας της επαφής <xliff:g id="SOURCE">%1$s</xliff:g> δεν μπορούν να υποβληθούν σε επεξεργασία σε αυτήν τη συσκευή."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Δεν υπάρχουν πρόσθετες πληροφορίες για αυτήν την επαφή"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Δεν έχουν επιλεγεί επαφές."</string>
<string name="add_field" msgid="2384260056674995230">"Προσθήκη άλλου πεδίου"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Προσθ. νέου αριθ. τηλ."</string>
+ <string name="add_email" msgid="175079666329862215">"Νέα διεύθ. ηλ. ταχ."</string>
+ <string name="add_im" msgid="5158094627521120439">"Προσθήκη νέου λογ. IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Προσθήκη νέας διεύθ."</string>
+ <string name="add_note" msgid="2753771325725383279">"Προσθ. νέας σημείωσης"</string>
+ <string name="add_website" msgid="4312391288948517344">"Προσθ. νέου ιστότοπου"</string>
+ <string name="add_event" msgid="7488781591843886426">"Προσθ. νέου συμβάντος"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Προσθήκη νέας σχέσης"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"μέσω <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> μέσω <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"αγαπημένο"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index a726674..ed3d6e5 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Default"</string>
<string name="removePhoto" msgid="4898105274130284565">"Remove photo"</string>
<string name="noContacts" msgid="8579310973261953559">"No contacts."</string>
+ <string name="noGroups" msgid="8614664663561385253">"No groups."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"No matching contacts found."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"No contacts with phone numbers."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Only contacts with phones"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> found"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contacts"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Groups"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favourites"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Phone"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Call log"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Call log is empty."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Clear call log"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Are you sure that you want to clear the call log?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Clearing call log"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Voicemail"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"No SD card detected"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Searching for vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Import from SIM card"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Import from storage"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Export to storage"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Import from storage"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Import from SD card"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Export to storage"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Export to SD card"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Share visible contacts"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Import one vCard file"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Import multiple vCard files"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Phonetic family name"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Phonetic name"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> contact"</string>
- <string name="from_account_format" msgid="687567483928582084">"from <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Use this photo"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> contact information cannot be edited on this device."</string>
<string name="no_contact_details" msgid="6754415338321837001">"No additional information for this contact"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"No contacts selected."</string>
<string name="add_field" msgid="2384260056674995230">"Add another field"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Add new phone number"</string>
+ <string name="add_email" msgid="175079666329862215">"Add new email"</string>
+ <string name="add_im" msgid="5158094627521120439">"Add new IM account"</string>
+ <string name="add_address" msgid="418292312672970688">"Add new address"</string>
+ <string name="add_note" msgid="2753771325725383279">"Add new note"</string>
+ <string name="add_website" msgid="4312391288948517344">"Add new website"</string>
+ <string name="add_event" msgid="7488781591843886426">"Add new event"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Add new relationship"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favourite"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 3d63100..fc96318 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predeterminado"</string>
<string name="removePhoto" msgid="4898105274130284565">"Eliminar foto"</string>
<string name="noContacts" msgid="8579310973261953559">"No hay contactos."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Ningún grupo"</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="showFilterPhones" msgid="4184858075465653970">"Sólo contactos con teléfonos"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g>Se encontró un"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contactos"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupos"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritos"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Teléfono"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Llamadas"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"El registro de llamadas está vacío."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Borrar registro de llamadas"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"¿Estás seguro de que deseas borrar el registro de llamadas?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Borrando el registro de llamadas"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Correo de voz"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"No se ha detectado ninguna tarjeta SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Buscando vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importar de la tarjeta SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importar desde el almacenamiento"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportar al almacenamiento"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importar desde el almacenamiento"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importar de la tarjeta SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportar al almacenamiento"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportar a la tarjeta SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Compartir contactos visibles"</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>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Apellido fonético"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nombre fonético"</string>
<string name="account_type_format" msgid="718948015590343010">"Contacto de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Usar esta foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"La información de <xliff:g id="SOURCE">%1$s</xliff:g> contactos no se puede editar en este dispositivo."</string>
<string name="no_contact_details" msgid="6754415338321837001">"No hay información adicional para este contacto."</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"No hay contactos seleccionados."</string>
<string name="add_field" msgid="2384260056674995230">"Agregar otro campo"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Agregar nuevo número de teléfono"</string>
+ <string name="add_email" msgid="175079666329862215">"Agregar nuevo correo"</string>
+ <string name="add_im" msgid="5158094627521120439">"Agregar nueva cuenta de MI"</string>
+ <string name="add_address" msgid="418292312672970688">"Agregar nueva dirección"</string>
+ <string name="add_note" msgid="2753771325725383279">"Agregar nueva nota"</string>
+ <string name="add_website" msgid="4312391288948517344">"Agregar nuevo sitio web"</string>
+ <string name="add_event" msgid="7488781591843886426">"Agregar nuevo evento"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Agregar nueva relación"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"a través de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> a través de <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorito"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index d659ab3..6623215 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predeterminado"</string>
<string name="removePhoto" msgid="4898105274130284565">"Eliminar foto"</string>
<string name="noContacts" msgid="8579310973261953559">"No hay ningún contacto."</string>
+ <string name="noGroups" msgid="8614664663561385253">"No hay grupos"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"No se ha encontrado ningún contacto coincidente."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"No hay ningún contacto con número de teléfono."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Solo contactos con teléfono"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> encontrados"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contactos"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupos"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritos"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Teléfono"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Llamadas"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"El registro de llamadas está vacío."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Borrar registro de llamadas"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"¿Estás seguro de que quieres borrar el registro de llamadas?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Borrando registro de llamadas"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Buzón de voz"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"No se ha detectado ninguna tarjeta SD."</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Buscando vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importar contactos desde la tarjeta SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importar de almacenamiento"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportar a almacenamiento"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importar de almacenamiento"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importar contactos desde la tarjeta SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportar a almacenamiento"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportar contactos a la tarjeta SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Compartir contactos visibles"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importar un archivo de vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importar varios archivos de vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Apellido fonético"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Transcripción fonética del nombre"</string>
<string name="account_type_format" msgid="718948015590343010">"Contacto de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilizar esta foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"No se puede editar la información del contacto de <xliff:g id="SOURCE">%1$s</xliff:g> en este dispositivo."</string>
<string name="no_contact_details" msgid="6754415338321837001">"No hay información adicional para este contacto."</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"No hay ningún contacto seleccionado."</string>
<string name="add_field" msgid="2384260056674995230">"Añadir otro campo"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Añadir nuevo teléfono"</string>
+ <string name="add_email" msgid="175079666329862215">"Añadir nuevo correo"</string>
+ <string name="add_im" msgid="5158094627521120439">"Añadir nueva cuenta MI"</string>
+ <string name="add_address" msgid="418292312672970688">"Añadir nueva dirección"</string>
+ <string name="add_note" msgid="2753771325725383279">"Añadir nueva nota"</string>
+ <string name="add_website" msgid="4312391288948517344">"Añadir nuevo sitio web"</string>
+ <string name="add_event" msgid="7488781591843886426">"Añadir nuevo evento"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Añadir nueva relación"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"con <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> con <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favoritos"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index e14b6ed..e3de006 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"پیش فرض"</string>
<string name="removePhoto" msgid="4898105274130284565">"حذف عکس"</string>
<string name="noContacts" msgid="8579310973261953559">"مخاطبی موجود نیست."</string>
+ <string name="noGroups" msgid="8614664663561385253">"گروهی وجود ندارد."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"مخاطب منطبقی یافت نشد."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"مخاطبی با شماره تلفن موجود نیست."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"فقط مخاطبین دارای شماره تلفن"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> یافت شد"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"مخاطبین"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"گروه ها"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"موارد دلخواه"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"تلفن"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"گزارش تماس"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"گزارش تماس خالی است."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"پاک کردن گزارش تماس"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"آیا مطمئن هستید که می خواهید گزارش تماس را پاک کنید؟"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"پاک کردن گزارش تماس"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"پست صوتی"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"هیچ کارت SD شناسایی نشد"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"جستجوی کارت ویزیت"</string>
<string name="import_from_sim" msgid="3859272228033941659">"وارد کردن از سیم کارت"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"وارد کردن از حافظه"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"صادر کردن به حافظه"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"وارد کردن از حافظه"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"وارد کردن از کارت SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"صادر کردن به حافظه"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"صدور به کارت SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"اشتراک گذاری مخاطبین قابل مشاهده"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"وارد کردن یک فایل کارت ویزیت"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"وارد کردن چند فایل کارت ویزیت"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"تلفظ آوایی نام خانوادگی"</string>
<string name="name_phonetic" msgid="4259595234312430484">"تلفظ نام"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> مخاطب"</string>
- <string name="from_account_format" msgid="687567483928582084">"از <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"استفاده از این عکس"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> اطلاعات مخاطب در این دستگاه قابل ویرایش نمی باشد."</string>
<string name="no_contact_details" msgid="6754415338321837001">"اطلاعات دیگری برای این مخاطب موجود نیست"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"مخاطبی انتخاب نشده است."</string>
<string name="add_field" msgid="2384260056674995230">"افزودن یک قسمت دیگر"</string>
+ <string name="add_phone" msgid="4421904942555210013">"افزودن شماره تلفن جدید"</string>
+ <string name="add_email" msgid="175079666329862215">"افزودن ایمیل جدید"</string>
+ <string name="add_im" msgid="5158094627521120439">"افزودن حساب IM جدید"</string>
+ <string name="add_address" msgid="418292312672970688">"افزودن آدرس جدید"</string>
+ <string name="add_note" msgid="2753771325725383279">"افزودن یادداشت جدید"</string>
+ <string name="add_website" msgid="4312391288948517344">"افزودن وب سایت جدید"</string>
+ <string name="add_event" msgid="7488781591843886426">"افزودن رویداد جدید"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"افزودن رابطه جدید"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"از طریق <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> از طریق <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"مورد دلخواه"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index a1547db..84b8ffb 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Oletus"</string>
<string name="removePhoto" msgid="4898105274130284565">"Poista kuva"</string>
<string name="noContacts" msgid="8579310973261953559">"Ei yhteystietoja."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Ei ryhmiä."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Hakua vastaavia yhteystietoja ei löydy."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Ei yhteystietoja, joissa on puhelinnumero."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Vain yhteystiedot, joissa on puhelinnumero"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Löytyi <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Yhteystiedot"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Ryhmät"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Suosikit"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Puhelin"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Puheluloki"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Puheluloki on tyhjä."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Tyhjennä puheluloki"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Haluatko varmasti tyhjentää puhelulokin?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Tyhjennetään puhelulokia"</string>
<string name="imei" msgid="3045126336951684285">"IMEI-koodi"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Vastaaja"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SD-korttia ei havaittu"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Etsitään vCardia"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Tuo SIM-kortilta"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Tuo tallennustilasta"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Vie tallennustilaan"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Tuo tallennustilasta"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Tuo SD-kortilta"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Vie tallennustilaan"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Vie SD-kortille"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Jaa näkyvät yhteystiedot"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Tuo yksi vCard-tiedosto"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Tuo useita vCard-tiedostoja"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Sukunimen ääntämistapa"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nimen ääntämistapa"</string>
<string name="account_type_format" msgid="718948015590343010">"Tilin <xliff:g id="SOURCE">%1$s</xliff:g> yhteystieto"</string>
- <string name="from_account_format" msgid="687567483928582084">"tilistä <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Käytä valokuvaa"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Tilin <xliff:g id="SOURCE">%1$s</xliff:g> yhteystietoja ei voi muokata tällä laitteella."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Tässä yhteystiedossa ei ole muita tietoja"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Ei valittuja yhteystietoja."</string>
<string name="add_field" msgid="2384260056674995230">"Lisää toinen kenttä"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Lisää uusi puh.numero"</string>
+ <string name="add_email" msgid="175079666329862215">"Lisää uusi sähköposti"</string>
+ <string name="add_im" msgid="5158094627521120439">"Lisää uusi pikav.tili"</string>
+ <string name="add_address" msgid="418292312672970688">"Lisää uusi osoite"</string>
+ <string name="add_note" msgid="2753771325725383279">"Lisää uusi huomautus"</string>
+ <string name="add_website" msgid="4312391288948517344">"Lisää uusi sivusto"</string>
+ <string name="add_event" msgid="7488781591843886426">"Lisää uusi tapahtuma"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Lisää uusi suhde"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"lähteestä: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> lähteestä: <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"lisää suosikkeihin"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index fae5446..b4a3e09 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Par défaut"</string>
<string name="removePhoto" msgid="4898105274130284565">"Supprimer la photo"</string>
<string name="noContacts" msgid="8579310973261953559">"Aucun contact."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Aucun groupe"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Aucun contact correspondant n\'a été trouvé."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Aucun contact disposant d\'un numéro téléphone."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Contacts avec un n° de tél."</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> contact(s) trouvé(s)"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contacts"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Groupes"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoris"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Tél."</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Appels"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Aucun appel."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Effacer le journal d\'appels"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Voulez-vous vraiment effacer le journal d\'appels ?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Suppression du journal d\'appels"</string>
<string name="imei" msgid="3045126336951684285">"Code IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Messagerie vocale"</string>
@@ -161,12 +164,12 @@
<string name="simContacts_title" msgid="27341688347689769">"Contacts de carte SIM"</string>
<string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"Vous n\'avez aucun contact à afficher. Si vous venez d\'ajouter un compte, la synchronisation des contacts peut prendre quelques minutes."</string>
<string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">"Vous n\'avez aucun contact à afficher."</string>
- <!-- syntax error in translation for noContactsHelpText (6450346791169710787) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:560 in java.io.StringReader@2666e815) -->
- <!-- syntax error in translation for noContactsHelpText (7633826236417884130) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:567 in java.io.StringReader@2e0ece65) -->
+ <!-- syntax error in translation for noContactsHelpText (6450346791169710787) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:560 in java.io.StringReader@3c6f579) -->
+ <!-- syntax error in translation for noContactsHelpText (7633826236417884130) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:567 in java.io.StringReader@7b1ddcde) -->
<string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"Vous n\'avez aucun contact à afficher (si vous venez d\'ajouter un compte, la synchronisation des contacts peut prendre quelques minutes)."\n\n"Pour ajouter des contacts, appuyez sur "<font fgcolor="#ffffffff"><b>"Menu"</b></font>", puis sur :"\n" "\n<li><font fgcolor="#ffffffff"><b>"Comptes"</b></font>" pour ajouter ou configurer un compte dont vous pourrez synchroniser les contacts vers la tablette ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Options d\'affichage"</b></font>" pour modifier les paramètres de visibilité des contacts ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nouveau contact"</b></font>" pour créer un contact ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/Exporter"</b></font>" pour importer des contacts depuis votre carte SIM ou SD."\n</li></string>
<string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"Vous n\'avez aucun contact à afficher (si vous venez d\'ajouter un compte, la synchronisation des contacts peut prendre quelques minutes)."\n\n"Pour ajouter des contacts, appuyez sur "<font fgcolor="#ffffffff"><b>"Menu"</b></font>" et sélectionnez :"\n" "\n<li><font fgcolor="#ffffffff"><b>"Comptes"</b></font>" pour ajouter ou configurer un compte dont vous pourrez synchroniser les contacts sur le téléphone ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Options d\'affichage"</b></font>" pour modifier le paramètre de visibilité des contacts ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nouveau contact"</b></font>" pour créer un contact ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/Exporter"</b></font>" pour importer des contacts depuis votre carte SIM ou SD."\n</li></string>
- <!-- syntax error in translation for noContactsNoSimHelpText (6031363021287849874) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:565 in java.io.StringReader@4e106082) -->
- <!-- syntax error in translation for noContactsNoSimHelpText (467658807711582876) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:571 in java.io.StringReader@15301ed8) -->
+ <!-- syntax error in translation for noContactsNoSimHelpText (6031363021287849874) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:565 in java.io.StringReader@658fb1f7) -->
+ <!-- syntax error in translation for noContactsNoSimHelpText (467658807711582876) org.xmlpull.v1.XmlPullParserException: expected: /b read: font (position:END_TAG </font>@1:571 in java.io.StringReader@3ced0338) -->
<string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"Vous n\'avez aucun contact à afficher (si vous venez d\'ajouter un compte, la synchronisation des contacts peut prendre quelques minutes)."\n\n"Pour ajouter des contacts, appuyez sur "<font fgcolor="#ffffffff"><b>"Menu"</b></font>", puis sur :"\n" "\n<li><font fgcolor="#ffffffff"><b>"Comptes"</b></font>" pour ajouter ou configurer un compte dont vous pourrez synchroniser les contacts vers la tablette ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Options d\'affichage"</b></font>" pour modifier les paramètres de visibilité des contacts ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nouveau contact"</b></font>" pour créer un contact ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/Exporter"</b></font>" pour importer des contacts depuis votre carte SD."\n</li></string>
<string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"Vous n\'avez aucun contact à afficher (si vous venez d\'ajouter un compte, la synchronisation des contacts peut prendre quelques minutes)."\n\n"Pour ajouter des contacts, appuyez sur "<font fgcolor="#ffffffff"><b>"Menu"</b></font>" et sélectionnez :"\n" "\n<li><font fgcolor="#ffffffff"><b>"Comptes"</b></font>" pour ajouter ou configurer un compte dont vous pourrez synchroniser les contacts sur le téléphone ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Options d\'affichage"</b></font>" pour modifier le paramètre de visibilité des contacts ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Nouveau contact"</b></font>" pour créer un contact ;"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/Exporter"</b></font>" pour importer des contacts depuis votre carte SD."\n</li></string>
<string name="noFavoritesHelpText" msgid="3744655776704833277">"Vous ne disposez d\'aucun favoris."\n\n"Pour ajouter un contact à la liste de favoris :"\n\n" "<li>"Appuyez sur l\'onglet "<b>"Contacts"</b>"."\n</li>" "\n<li>"Appuyez sur le contact à ajouter à vos favoris."\n</li>" "\n<li>"Appuyez sur l\'étoile en regard du nom du contact."\n</li></string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Aucune carte SD n\'a été détectée."</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Recherche des données VCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importer à partir de la carte SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importer depuis mémoire"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exporter vers la mémoire"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importer depuis mémoire"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importer à partir de la carte SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exporter vers la mémoire"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exporter vers la carte SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Partager les contacts visibles"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importer un fichier vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importer plusieurs fichiers vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Phonétique du nom de famille"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nom phonétique"</string>
<string name="account_type_format" msgid="718948015590343010">"Contact <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utiliser cette photo"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Vous ne pouvez pas modifier les informations du contact <xliff:g id="SOURCE">%1$s</xliff:g> sur cet appareil."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Aucune autre information pour ce contact"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Aucun contact sélectionné"</string>
<string name="add_field" msgid="2384260056674995230">"Ajouter un champ"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Ajouter un numéro"</string>
+ <string name="add_email" msgid="175079666329862215">"Ajouter adresse e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Ajouter compte chat"</string>
+ <string name="add_address" msgid="418292312672970688">"Ajouter une adresse"</string>
+ <string name="add_note" msgid="2753771325725383279">"Ajouter une remarque"</string>
+ <string name="add_website" msgid="4312391288948517344">"Ajouter un site Web"</string>
+ <string name="add_event" msgid="7488781591843886426">"Ajouter un événement"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Ajouter une relation"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favori"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index d90ae86..e2bc4f5 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Zadano"</string>
<string name="removePhoto" msgid="4898105274130284565">"Ukloni fotografiju"</string>
<string name="noContacts" msgid="8579310973261953559">"Nema kontakata."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nema grupa."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nisu pronađeni podudarni kontakti."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nema kontakata s telefonskim brojevima."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Samo kontakti s telefonima"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Pronađeno kontakata: <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakti"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupe"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoriti"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Zapisnik poziva"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Zapisnik poziva je prazan"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Izbriši zapisnik poziva"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Jeste li sigurni da želite izbrisati zapisnik poziva?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Brisanje zapisnika poziva"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Govorna pošta"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nije pronađena SD kartica"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Traženje kartice vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Uvezi sa SIM kartice"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Uvoz iz pohrane"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Izvoz u pohranu"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Uvoz iz pohrane"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Uvezi sa SD kartice"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Izvoz u pohranu"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Izvoz na SD karticu"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Dijeli vidljive kontakte"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Uvezi jednu vCard datoteku"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Uvoz više vCard datoteka"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetsko prezime"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Ime fonetski"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kontakt"</string>
- <string name="from_account_format" msgid="687567483928582084">"s lokacije <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Upotrijebi ovu fotografiju"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> informacije kontakta nije moguće uređivati na ovom uređaju."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nema dodatnih informacija za ovaj kontakt"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nije odabran nijedan kontakt."</string>
<string name="add_field" msgid="2384260056674995230">"Dodaj drugo polje"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Dodajte novi tel. broj"</string>
+ <string name="add_email" msgid="175079666329862215">"Dodajte novu e-poštu"</string>
+ <string name="add_im" msgid="5158094627521120439">"Dodajte novi IM račun"</string>
+ <string name="add_address" msgid="418292312672970688">"Dodajte novu adresu"</string>
+ <string name="add_note" msgid="2753771325725383279">"Dodajte novu napomenu"</string>
+ <string name="add_website" msgid="4312391288948517344">"Dodajte novu stranicu"</string>
+ <string name="add_event" msgid="7488781591843886426">"Dodajte novi događaj"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Dodajte novi odnos"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"preko izvora <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> preko izvora <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorit"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 38558a9..9c3fd10 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Alapértelmezett"</string>
<string name="removePhoto" msgid="4898105274130284565">"Fénykép törlése"</string>
<string name="noContacts" msgid="8579310973261953559">"Nincsenek névjegyek."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nincsenek csoportok"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nincsenek a keresési feltételeknek megfelelő névjegyek."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nincsenek telefonszámot is tartalmazó névjegyek."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Csak a telefonszámmal rendelkező névjegyek"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> találat"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Címtár"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Csoportok"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Kedvencek"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Híváslista"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"A híváslista üres."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Híváslista törlése"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Biztosan törli a híváslistát?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Hívási napló törölve"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Hangposta"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Az SD-kártya nem észlelhető"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCard keresése"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importálás a SIM-kártyáról"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importálás a tárhelyről"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportálás a tárhelyre"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importálás a tárhelyről"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importálás az SD-kártyáról"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportálás a tárhelyre"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportálás SD-kártyára"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Látható névjegyek megosztása"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Egyetlen vCard fájl importálása"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Több vCard fájl importálása"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Vezetéknév fonetikusan"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Név fonetikusan"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> névjegy"</string>
- <string name="from_account_format" msgid="687567483928582084">"<xliff:g id="SOURCE">%1$s</xliff:g> fiókból"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Fotó felhasználása"</string>
<string name="contact_read_only" msgid="1203216914575723978">"A(z) <xliff:g id="SOURCE">%1$s</xliff:g> névjegyadatai nem szerkeszthetők ezen az eszközön."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nincsenek további adatok ennél a névjegynél"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nincs kijelölt névjegy."</string>
<string name="add_field" msgid="2384260056674995230">"Más mező hozzáadása"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Új telefonszám"</string>
+ <string name="add_email" msgid="175079666329862215">"Új e-mail hozzáadása"</string>
+ <string name="add_im" msgid="5158094627521120439">"Új IM-fiók hozzáadása"</string>
+ <string name="add_address" msgid="418292312672970688">"Új cím hozzáadása"</string>
+ <string name="add_note" msgid="2753771325725383279">"Új megjegyzés"</string>
+ <string name="add_website" msgid="4312391288948517344">"Új webhely hozzáadása"</string>
+ <string name="add_event" msgid="7488781591843886426">"Új esemény hozzáadása"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Új kapcsolat"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"- <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> - <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"kedvenc"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index b690843..0135510 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Bawaan"</string>
<string name="removePhoto" msgid="4898105274130284565">"Hapus foto"</string>
<string name="noContacts" msgid="8579310973261953559">"Tidak ada kenalan."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Tidak ada grup."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Tidak ditemukan kenalan yang cocok."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Tidak ada kenalan dengan nomor telepon."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Hanya kenalan dengan telepon"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Ada <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kenalan"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grup"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favorit"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telepon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Log panggilan"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Log panggilan kosong."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Hapus log panggilan"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Apakah Anda yakin ingin menghapus log panggilan?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Membersihkan log panggilan"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Kotak Pesan"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Tidak ada kartu SD yang terdeteksi"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Menelusuri vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Impor dari kartu SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Impor dari penyimpanan"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Ekspor ke penyimpanan"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Impor dari penyimpanan"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Impor dari kartu SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Ekspor ke penyimpanan"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Ekspor ke kartu SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Bagikan kenalan yang terlihat"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Impor satu berkas vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Impor beberapa berkas vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Nama keluarga fonetik"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nama fonetik"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kenalan"</string>
- <string name="from_account_format" msgid="687567483928582084">"dari <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Gunakan foto ini"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Informasi kenalan <xliff:g id="SOURCE">%1$s</xliff:g> tidak dapat diedit pada perangkat ini."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Tidak ada informasi tambahan untuk kenalan ini"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Tidak ada kenalan yang dipilih."</string>
<string name="add_field" msgid="2384260056674995230">"Tambahkan bidang lain"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Menambah no. tlp. baru"</string>
+ <string name="add_email" msgid="175079666329862215">"Menambah email baru"</string>
+ <string name="add_im" msgid="5158094627521120439">"Menambah akun IM baru"</string>
+ <string name="add_address" msgid="418292312672970688">"Menambah alamat baru"</string>
+ <string name="add_note" msgid="2753771325725383279">"Menambah catatan baru"</string>
+ <string name="add_website" msgid="4312391288948517344">"Menambah situs baru"</string>
+ <string name="add_event" msgid="7488781591843886426">"Menambah acara baru"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Menambah hubungan baru"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"melalui <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> melalui <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorit"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index e096cda..a64e592 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predefinita"</string>
<string name="removePhoto" msgid="4898105274130284565">"Rimuovi foto"</string>
<string name="noContacts" msgid="8579310973261953559">"Nessun contatto."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nessun gruppo."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nessun contatto corrispondente trovato."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nessun contatto con numeri di telefono."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Solo contatti con numeri di tel."</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> trovati"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contatti"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Gruppi"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Preferiti"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefono"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Chiamate"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Il registro chiamate è vuoto."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Cancella registro chiamate"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Cancellare il registro chiamate?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Cancellazione registro chiamate"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Segreteria"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nessuna scheda SD rilevata"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Ricerca vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importa da scheda SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importa da archivio"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Esporta in archivio"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importa da archivio"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importa da scheda SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Esporta in archivio"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Esporta su scheda SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Condividi contatti visibili"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importa un file vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importa più file vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Cognome fonetico"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nome fonetico"</string>
<string name="account_type_format" msgid="718948015590343010">"Contatto da <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"da <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilizza questa foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Informazioni del contatto da <xliff:g id="SOURCE">%1$s</xliff:g> non modificabili su questo dispositivo."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nessuna informazione aggiuntiva per questo contatto"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nessun contatto selezionato."</string>
<string name="add_field" msgid="2384260056674995230">"Aggiungi un altro campo"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Nuovo n. telefono"</string>
+ <string name="add_email" msgid="175079666329862215">"Nuova email"</string>
+ <string name="add_im" msgid="5158094627521120439">"Nuovo account IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Nuovo indirizzo"</string>
+ <string name="add_note" msgid="2753771325725383279">"Nuova nota"</string>
+ <string name="add_website" msgid="4312391288948517344">"Nuovo sito web"</string>
+ <string name="add_event" msgid="7488781591843886426">"Nuovo evento"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Nuova relazione"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"tramite <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> tramite <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"preferiti"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index acbea6c..895fd29 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"ברירת מחדל"</string>
<string name="removePhoto" msgid="4898105274130284565">"הסר תמונה"</string>
<string name="noContacts" msgid="8579310973261953559">"אין אנשי קשר."</string>
+ <string name="noGroups" msgid="8614664663561385253">"אין קבוצות."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"לא נמצאו אנשי קשר תואמים."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"אין אנשי קשר עם מספרי טלפון."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"רק אנשי קשר עם מספרי טלפון"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> נמצאו"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"אנשי קשר"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"קבוצות"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"מועדפים"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"טלפון"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"יומן שיחות"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"יומן השיחות ריק."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"נקה את יומן השיחות"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"האם אתה בטוח שברצונך לנקות את יומן השיחות?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"ניקוי יומן שיחות"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"דואר קולי"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"לא אותר כרטיס SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"מחפש vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"ייבא מכרטיס SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"ייבא מאמצעי אחסון"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"ייצא לאמצעי אחסון"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"ייבא מאמצעי אחסון"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"ייבא מכרטיס SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"ייצא לאמצעי אחסון"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"ייצא לכרטיס SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"שתף אנשי קשר גלויים"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"ייבא קובץ אחד של vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"ייבא קובצי vCard מרובים"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"שם משפחה פונטי"</string>
<string name="name_phonetic" msgid="4259595234312430484">"שם פונטי"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g>איש קשר"</string>
- <string name="from_account_format" msgid="687567483928582084">"מ-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"השתמש בתמונה זו"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> פרטי איש הקשר אינם ניתנים לעריכה במכשיר זה."</string>
<string name="no_contact_details" msgid="6754415338321837001">"אין מידע נוסף על איש קשר זה"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"לא נבחרו אנשי קשר."</string>
<string name="add_field" msgid="2384260056674995230">"הוסף שדה נוסף"</string>
+ <string name="add_phone" msgid="4421904942555210013">"הוסף מספר טלפון חדש"</string>
+ <string name="add_email" msgid="175079666329862215">"הוסף דוא\"ל חדש"</string>
+ <string name="add_im" msgid="5158094627521120439">"הוסף חשבון IM חדש"</string>
+ <string name="add_address" msgid="418292312672970688">"הוסף כתובת חדשה"</string>
+ <string name="add_note" msgid="2753771325725383279">"הוסף הערה חדשה"</string>
+ <string name="add_website" msgid="4312391288948517344">"הוסף אתר חדש"</string>
+ <string name="add_event" msgid="7488781591843886426">"הוסף אירוע חדש"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"הוסף קשר חדש"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"דרך <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> דרך <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"מועדף"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index eeb9715..17f7624 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"プリセット着信音"</string>
<string name="removePhoto" msgid="4898105274130284565">"写真を削除"</string>
<string name="noContacts" msgid="8579310973261953559">"連絡先がありません。"</string>
+ <string name="noGroups" msgid="8614664663561385253">"グループはありません。"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"一致する連絡先が見つかりません。"</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"電話番号付きの連絡先はありません。"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"電話番号のある連絡先のみ"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g>件見つかりました"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"連絡先"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"グループ"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"お気入り"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"電話"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"通話履歴"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"通話履歴なし"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"通話履歴を消去"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"通話履歴を消去してもよろしいですか?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"通話履歴の消去中"</string>
<string name="imei" msgid="3045126336951684285">"IMEI(端末識別番号)"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"ボイスメール"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SDカードを検出できませんでした"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCardを検索中"</string>
<string name="import_from_sim" msgid="3859272228033941659">"SIMカードからインポート"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"ストレージからインポート"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"ストレージにエクスポート"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"ストレージからインポート"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"SDカードからインポート"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"ストレージにエクスポート"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"SDカードにエクスポート"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"表示可能な連絡先を共有"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"vCardファイルを1つインポート"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"複数のvCardファイルをインポート"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"姓のよみがな"</string>
<string name="name_phonetic" msgid="4259595234312430484">"よみがな"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g>からの連絡先"</string>
- <string name="from_account_format" msgid="687567483928582084">"<xliff:g id="SOURCE">%1$s</xliff:g>からの連絡先"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"この写真を使用"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g>からの連絡先情報はこの携帯端末では編集できません。"</string>
<string name="no_contact_details" msgid="6754415338321837001">"この連絡先の詳細情報はありません"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"連絡先が選択されていません。"</string>
<string name="add_field" msgid="2384260056674995230">"別のフィールドを追加"</string>
+ <string name="add_phone" msgid="4421904942555210013">"新しい電話番号を追加"</string>
+ <string name="add_email" msgid="175079666329862215">"新しいメールを追加"</string>
+ <string name="add_im" msgid="5158094627521120439">"新規IMアカウントを追加"</string>
+ <string name="add_address" msgid="418292312672970688">"新しい住所を追加"</string>
+ <string name="add_note" msgid="2753771325725383279">"新しいメモを追加"</string>
+ <string name="add_website" msgid="4312391288948517344">"新しいサイトを追加"</string>
+ <string name="add_event" msgid="7488781591843886426">"新しいイベントを追加"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"新しい関係を追加"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"<xliff:g id="SOURCE">%1$s</xliff:g>経由"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>、<xliff:g id="SOURCE">%2$s</xliff:g>経由"</string>
<string name="description_star" msgid="2605854427360036550">"お気に入り"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 4413a1f..cc00827 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"기본값"</string>
<string name="removePhoto" msgid="4898105274130284565">"사진 삭제"</string>
<string name="noContacts" msgid="8579310973261953559">"주소록이 없습니다."</string>
+ <string name="noGroups" msgid="8614664663561385253">"그룹 없음"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"일치하는 연락처가 없습니다."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"전화번호가 포함된 주소록이 없습니다."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"전화번호가 있는 연락처만"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g>개를 찾았습니다."</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"주소록"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"그룹"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"즐겨찾기"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"휴대전화"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"통화기록"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"통화기록이 없습니다."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"통화 기록 지우기"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"통화 기록을 삭제하시겠습니까?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"통화기록 지우기"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"음성사서함"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SD 카드가 발견되지 않았습니다."</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCard 검색"</string>
<string name="import_from_sim" msgid="3859272228033941659">"SIM 카드에서 가져오기"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"저장장치에서 가져오기"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"저장공간으로 내보내기"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"저장장치에서 가져오기"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"SD 카드에서 가져오기"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"저장공간으로 내보내기"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"SD 카드로 내보내기"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"표시되는 연락처 모두 공유"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"vCard 파일 한 개 가져오기"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"vCard 파일 여러 개 가져오기"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"성(소리나는 대로)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"이름(소리나는 대로)"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> 연락처"</string>
- <string name="from_account_format" msgid="687567483928582084">"출처: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"사진 사용"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> 연락처 정보는 이 기기에서 수정할 수 없습니다."</string>
<string name="no_contact_details" msgid="6754415338321837001">"연락처에 대한 추가 정보가 없습니다."</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"선택한 연락처가 없습니다."</string>
<string name="add_field" msgid="2384260056674995230">"다른 입력란 추가"</string>
+ <string name="add_phone" msgid="4421904942555210013">"새 전화번호 추가"</string>
+ <string name="add_email" msgid="175079666329862215">"새 이메일 추가"</string>
+ <string name="add_im" msgid="5158094627521120439">"새 메신저 계정 추가"</string>
+ <string name="add_address" msgid="418292312672970688">"새 주소 추가"</string>
+ <string name="add_note" msgid="2753771325725383279">"새 메모 추가"</string>
+ <string name="add_website" msgid="4312391288948517344">"새 웹사이트 추가"</string>
+ <string name="add_event" msgid="7488781591843886426">"새 일정 추가"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"새 관계 추가"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"출처: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>(출처: <xliff:g id="SOURCE">%2$s</xliff:g>)"</string>
<string name="description_star" msgid="2605854427360036550">"즐겨찾기"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index bf3512a..ecc986b 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Numatytasis"</string>
<string name="removePhoto" msgid="4898105274130284565">"Pašalinti nuotrauką"</string>
<string name="noContacts" msgid="8579310973261953559">"Adresatų nėra."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nėra grupių."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nerasta atitinkančių adresatų."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nėra adresatų su telefono numeriais."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Tik adresatai su telefono numeriais"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Rasta <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Adresinė"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupės"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Adresynas"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefonas"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Skambučių žurnalas"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Skambučių žurnalas tuščias."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Išvalyti skambučių žurnalą"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Ar tikrai norite išvalyti skambučių žurnalą?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Valomas skambučių žurnalas"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Balso paštas"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SD kortelė neaptikta"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Ieškoma „vCard“ kortelės"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importuoti iš SIM kortelės"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importuoti iš saugyklos"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Eksportuoti į saugyklą"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importuoti iš saugyklos"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importuoti iš SD kortelės"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Eksportuoti į saugyklą"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Eksportuoti į SD kortelę"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Bendrinti matomus adresatus"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importuoti vieną „vCard“ failą"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importuoti kelis „vCard“ failus"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetinė pavardė"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetinis vardas"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> adresatas"</string>
- <string name="from_account_format" msgid="687567483928582084">"nuo <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Naudoti šią nuotrauką"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> adresato informacijos šiame įrenginyje redaguoti negalima."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nėra papildomos informacijos apie šį adresatą"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nepasirinkote kontaktų."</string>
<string name="add_field" msgid="2384260056674995230">"Pridėti kitą lauką"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Pridėti naują tel. nr."</string>
+ <string name="add_email" msgid="175079666329862215">"Prid. n. el. pšt. adr."</string>
+ <string name="add_im" msgid="5158094627521120439">"Pridėti naują TP pask."</string>
+ <string name="add_address" msgid="418292312672970688">"Pridėti naują adresą"</string>
+ <string name="add_note" msgid="2753771325725383279">"Pridėti naują pastabą"</string>
+ <string name="add_website" msgid="4312391288948517344">"Pridėti naują svetainę"</string>
+ <string name="add_event" msgid="7488781591843886426">"Pridėti naują įvykį"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Pridėti naujus santyk."</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"naudojant „<xliff:g id="SOURCE">%1$s</xliff:g>“"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> naudojant „<xliff:g id="SOURCE">%2$s</xliff:g>“"</string>
<string name="description_star" msgid="2605854427360036550">"įtraukti į adresyną"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index d0cd6bf..11369cf 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Noklusējums"</string>
<string name="removePhoto" msgid="4898105274130284565">"Noņemt fotoattēlu"</string>
<string name="noContacts" msgid="8579310973261953559">"Nav kontaktpersonu."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nav grupu."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nav atrasta neviena atbilstoša kontaktpersona."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nav nevienas kontaktpersonas ar tālruņa numuru."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Tikai kontaktpersonas ar tālruņiem"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Atrastas <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontaktpersonas"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupas"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Izlase"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Zvanīt"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Zvanu žurnāls"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Zvanu žurnāls ir tukšs."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Notīrīt zvanu žurnālu"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Vai tiešām vēlaties notīrīt zvanu žurnālu?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Zvanu žurnāla tīrīšana"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Balss pasts"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SD karte nav noteikta."</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCard faila meklēšana"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importēt no SIM kartes"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importēt no USB atmiņas"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Eksportēt uz USB atmiņu"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importēt no USB atmiņas"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importēt no SD kartes"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Eksportēt uz USB atmiņu"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Eksportēt uz SD karti"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Kopīgot redzamās kontaktpersonas"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importēt vienu vCard failu"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importēt vairākus vCard failus"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Uzvārda izruna"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Vārda izruna"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kontaktpersona"</string>
- <string name="from_account_format" msgid="687567483928582084">"no <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Izmantot šo fotoattēlu"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Kontaktinformāciju no pakalpojuma <xliff:g id="SOURCE">%1$s</xliff:g> šajā ierīcē nevar rediģēt."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nav pieejama papildu informācija par šo kontaktpersonu."</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nav atlasīta neviena kontaktpersona."</string>
<string name="add_field" msgid="2384260056674995230">"Pievienot vēl vienu lauku"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Piev. jaunu tālr. nr."</string>
+ <string name="add_email" msgid="175079666329862215">"Piev. jaunu e-pastu"</string>
+ <string name="add_im" msgid="5158094627521120439">"Piev. jaunu t. ziņ. k."</string>
+ <string name="add_address" msgid="418292312672970688">"Pievienot jaunu adresi"</string>
+ <string name="add_note" msgid="2753771325725383279">"Piev. jaunu piezīmi"</string>
+ <string name="add_website" msgid="4312391288948517344">"Pievienot jaunu vietni"</string>
+ <string name="add_event" msgid="7488781591843886426">"Piev. jaunu notikumu"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Piev. jaunu saistību"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"izmantojot <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>, izmantojot <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"izlase"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
new file mode 100644
index 0000000..4a81f64
--- /dev/null
+++ b/res/values-ms/strings.xml
@@ -0,0 +1,824 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for sharedUserLabel (7965035505237135241) -->
+ <skip />
+ <string name="contactsList" msgid="8661624236494819731">"Kenalan"</string>
+ <!-- no translation found for launcherDialer (8636288196618486553) -->
+ <skip />
+ <string name="shortcutContact" msgid="749243779392912958">"Kenalan"</string>
+ <!-- no translation found for shortcutDialContact (746622101599186779) -->
+ <skip />
+ <!-- no translation found for shortcutMessageContact (2460337253595976198) -->
+ <skip />
+ <string name="shortcutActivityTitle" msgid="6642877210643565436">"Pilih pintasan kenalan"</string>
+ <string name="callShortcutActivityTitle" msgid="6065749861423648991">"Pilih nombor untuk memanggil"</string>
+ <string name="messageShortcutActivityTitle" msgid="3084542316620335911">"Pilih nombor untuk menghantar mesej"</string>
+ <!-- no translation found for contactPickerActivityTitle (6886592363525235031) -->
+ <skip />
+ <string name="starredList" msgid="4817256136413959463">"Dibintangkan"</string>
+ <string name="frequentList" msgid="7154768136473953056">"Kerap"</string>
+ <string name="strequentList" msgid="5640192862059373511">"Kegemaran"</string>
+ <string name="viewContactTitle" msgid="7989394521836644384">"Butiran kenalan"</string>
+ <string name="viewContactDesription" msgid="214186610887547860">"Papar kenalan"</string>
+ <string name="editContactDescription" msgid="2947202828256214947">"Edit kenalan"</string>
+ <string name="insertContactDescription" msgid="4709878105452681987">"Wujudkan kenalan"</string>
+ <string name="searchHint" msgid="8482945356247760701">"Cari dalam kenalan"</string>
+ <string name="menu_search" msgid="9147752853603483719">"Cari"</string>
+ <string name="menu_newContact" msgid="1209922412763274638">"Kenalan baru"</string>
+ <string name="menu_viewContact" msgid="2795575601596468581">"Papar kenalan"</string>
+ <string name="menu_callNumber" msgid="5142851348489387516">"Panggil <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="menu_addStar" msgid="2908478235715404876">"Tambah ke kegemaran"</string>
+ <string name="menu_removeStar" msgid="5844227078364227030">"Alih keluar daripada kegemaran"</string>
+ <string name="menu_editContact" msgid="3452858480713561396">"Edit kenalan"</string>
+ <string name="menu_deleteContact" msgid="1916555454274101750">"Padam kenalan"</string>
+ <!-- no translation found for menu_call (3992595586042260618) -->
+ <skip />
+ <!-- no translation found for menu_sendSMS (5535886767547006515) -->
+ <skip />
+ <!-- no translation found for menu_makeDefaultEmail (2599044610375789994) -->
+ <skip />
+ <!-- no translation found for menu_splitAggregate (8368636463748691868) -->
+ <skip />
+ <!-- no translation found for menu_renameGroup (2798886925154156075) -->
+ <skip />
+ <!-- no translation found for menu_deleteGroup (644571524292675446) -->
+ <skip />
+ <!-- no translation found for menu_new_contact_action_bar (8887818026717394343) -->
+ <skip />
+ <!-- no translation found for splitConfirmation_title (6716467920283502570) -->
+ <skip />
+ <!-- no translation found for splitConfirmation (1150797297503944823) -->
+ <skip />
+ <!-- no translation found for menu_joinAggregate (5027981918265667970) -->
+ <skip />
+ <!-- no translation found for titleJoinContactDataWith (7684875775798635354) -->
+ <skip />
+ <!-- no translation found for blurbJoinContactDataWith (995870557595050304) -->
+ <skip />
+ <!-- no translation found for showAllContactsJoinItem (2189695051430392383) -->
+ <skip />
+ <!-- no translation found for separatorJoinAggregateSuggestions (2831414448851313345) -->
+ <skip />
+ <!-- no translation found for separatorJoinAggregateAll (7939932265026181043) -->
+ <skip />
+ <!-- no translation found for contactsJoinedMessage (7208148163607047389) -->
+ <skip />
+ <!-- no translation found for menu_contactOptions (1957061455705020617) -->
+ <skip />
+ <!-- no translation found for contactOptionsTitle (8259347644090700915) -->
+ <skip />
+ <string name="deleteConfirmation_title" msgid="6394309508930335204">"Padam"</string>
+ <!-- no translation found for readOnlyContactWarning (1390849295342594265) -->
+ <skip />
+ <!-- no translation found for readOnlyContactDeleteConfirmation (2137170726670196909) -->
+ <skip />
+ <!-- no translation found for multipleContactDeleteConfirmation (938900978442960800) -->
+ <skip />
+ <string name="deleteConfirmation" msgid="811706994761610640">"Kenalan ini akan dipadamkan."</string>
+ <string name="menu_done" msgid="796017761764190697">"Selesai"</string>
+ <!-- outdated translation 2174577548513895144 --> <string name="menu_doNotSave" msgid="58593876893538465">"Berbalik"</string>
+ <string name="editContact_title_edit" msgid="7678695190666836093">"Edit kenalan"</string>
+ <string name="editContact_title_insert" msgid="9125600232291405757">"Kenalan baru"</string>
+ <string name="label_phonetic_name" msgid="2288082649573927286">"Fonetik"</string>
+ <string name="label_notes" msgid="8337354953278341042">"Nota"</string>
+ <!-- no translation found for label_sip_address (124073911714324974) -->
+ <skip />
+ <string name="label_ringtone" msgid="8833166825330686244">"Nada dering"</string>
+ <string name="ghostData_phonetic_name" msgid="7852749081984070902">"Nama fonetik"</string>
+ <string name="ghostData_company" msgid="5414421120553765775">"Syarikat"</string>
+ <!-- outdated translation 7662602222400641187 --> <string name="ghostData_title" msgid="7496735200318496110">"Kedudukan"</string>
+ <string name="invalidContactMessage" msgid="5816991830260044593">"Kenalan tidak wujud."</string>
+ <string name="pickerNewContactHeader" msgid="7750705279843568147">"Wujudkan kenalan baru"</string>
+ <string name="phoneLabelsGroup" msgid="6468091477851199285">"Telefon"</string>
+ <string name="emailLabelsGroup" msgid="8389931313045344406">"E-mel"</string>
+ <string name="imLabelsGroup" msgid="3898238486262614027">"IM"</string>
+ <!-- outdated translation 1618078212734693682 --> <string name="postalLabelsGroup" msgid="3487738141112589324">"Alamat pos"</string>
+ <string-array name="otherLabels">
+ <item msgid="8287841928119937597">"Organisasi"</item>
+ <item msgid="7196592230748086755">"Nota"</item>
+ </string-array>
+ <!-- outdated translation 431331662154342581 --> <string name="photoPickerNotFoundText" product="tablet" msgid="6247290728908599701">"Tidak ada gambar yang tersedia pada telefon."</string>
+ <string name="photoPickerNotFoundText" product="default" msgid="431331662154342581">"Tidak ada gambar yang tersedia pada telefon."</string>
+ <!-- no translation found for attach_photo_dialog_title (5599827035558557169) -->
+ <skip />
+ <string name="customLabelPickerTitle" msgid="1081475101983255212">"Label nama peribadi"</string>
+ <!-- no translation found for menu_displayGroup (5655505437727616553) -->
+ <skip />
+ <string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"Hantar panggilan terus ke peti suara"</string>
+ <string name="default_ringtone" msgid="9099988849649827972">"Lalai"</string>
+ <!-- no translation found for removePhoto (4898105274130284565) -->
+ <skip />
+ <string name="noContacts" msgid="8579310973261953559">"Tiada kenalan."</string>
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
+ <!-- no translation found for noMatchingContacts (4266283206853990471) -->
+ <skip />
+ <string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Tiada kenalan dengan nombor telefon."</string>
+ <!-- no translation found for showFilterPhones (4184858075465653970) -->
+ <skip />
+ <!-- no translation found for showFilterPhonesDescrip (6644443248815191067) -->
+ <skip />
+ <!-- no translation found for headerContactGroups (2426134991932503843) -->
+ <skip />
+ <!-- no translation found for groupDescrip:other (3507881585720628389) -->
+ <!-- no translation found for groupDescripPhones:other (3816047547470490208) -->
+ <!-- no translation found for savingContact (4075751076741924939) -->
+ <skip />
+ <!-- no translation found for savingDisplayGroups (2133152192716475939) -->
+ <skip />
+ <string name="contactSavedToast" msgid="7152589189385441091">"Kenalan disimpan."</string>
+ <!-- no translation found for contactSavedErrorToast (9189098776225004666) -->
+ <skip />
+ <!-- no translation found for listTotalPhoneContacts:one (3015357862286673986) -->
+ <!-- no translation found for listTotalPhoneContacts:other (3299954047880968205) -->
+ <!-- no translation found for listTotalPhoneContactsZero (6968813857632984319) -->
+ <skip />
+ <!-- no translation found for listTotalAllContacts:one (3405747744700823280) -->
+ <!-- no translation found for listTotalAllContacts:other (3578469907265375314) -->
+ <!-- no translation found for listTotalAllContactsZero (1889349925514589304) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroCustom (4058252141420128998) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroStarred (5391630590684099117) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroGroup (5448979458248027615) -->
+ <skip />
+ <!-- no translation found for listFoundAllContacts:one (5517063038754171134) -->
+ <!-- no translation found for listFoundAllContacts:other (3852668542926965042) -->
+ <!-- no translation found for foundTooManyContacts (2548148047461758967) -->
+ <skip />
+ <!-- no translation found for listFoundAllContactsZero (777952841930508289) -->
+ <skip />
+ <!-- no translation found for searchFoundContacts:one (4826918429708286628) -->
+ <!-- no translation found for searchFoundContacts:other (7988132539476575389) -->
+ <string name="contactsIconLabel" msgid="7666609097606552806">"Kenalan"</string>
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
+ <string name="contactsFavoritesLabel" msgid="8417039765586853670">"Kegemaran"</string>
+ <!-- no translation found for dialerIconLabel (6500826552823403796) -->
+ <skip />
+ <string name="recentCallsIconLabel" msgid="1419116422359067949">"Log panggilan"</string>
+ <string name="liveFolderAll" msgid="4789010460767506206">"Semua kenalan"</string>
+ <string name="liveFolderFavorites" msgid="3100957542927222282">"Kenalan yang dibintangkan"</string>
+ <string name="liveFolderPhone" msgid="3739376066610926780">"Kenalan dengan nombor telefon"</string>
+ <!-- no translation found for menu_sendTextMessage (6937343460284499306) -->
+ <skip />
+ <string name="recentCalls_callNumber" msgid="1756372533999226126">"Panggil <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="recentCalls_editNumberBeforeCall" msgid="7756171675833267857">"Edit nombor sebelum panggilan"</string>
+ <string name="recentCalls_addToContact" msgid="1429899535546487008">"Tambah ke kenalan"</string>
+ <string name="recentCalls_removeFromRecentList" msgid="401662244636511330">"Alih keluar daripada log panggilan"</string>
+ <string name="recentCalls_deleteAll" msgid="6352364392762163704">"Padam bersih log panggilan"</string>
+ <string name="recentCalls_empty" msgid="247053222448663107">"Log panggilan kosong."</string>
+ <!-- no translation found for clearCallLogConfirmation_title (718072843006222703) -->
+ <skip />
+ <!-- no translation found for clearCallLogConfirmation (7625927669136267636) -->
+ <skip />
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
+ <string name="imei" msgid="3045126336951684285">"IMEI"</string>
+ <!-- no translation found for meid (6210568493746275750) -->
+ <skip />
+ <string name="voicemail" msgid="3851469869202611441">"Mel suara"</string>
+ <string name="unknown" msgid="740067747858270469">"Tidak diketahui"</string>
+ <string name="private_num" msgid="6374339738119166953">"Nombor peribadi"</string>
+ <string name="payphone" msgid="4864313342828942922">"Telefon awam"</string>
+ <string name="dialerKeyboardHintText" msgid="5401660096579787344">"Gunakan papan kekunci untuk mendail"</string>
+ <string name="dialerDialpadHintText" msgid="5824490365898349041">"Dail untuk menambah panggilan"</string>
+ <string name="simContacts_emptyLoading" msgid="6700035985448642408">"Memuatkan dari kad SIM..."</string>
+ <string name="simContacts_title" msgid="27341688347689769">"Kenalan kad SIM"</string>
+ <!-- no translation found for noContactsHelpTextWithSyncForCreateShortcut (801504710275614594) -->
+ <skip />
+ <!-- no translation found for noContactsHelpTextForCreateShortcut (3081286388667108335) -->
+ <skip />
+ <!-- no translation found for noContactsHelpText (6450346791169710787) -->
+ <skip />
+ <!-- no translation found for noContactsHelpText (7633826236417884130) -->
+ <skip />
+ <!-- no translation found for noContactsHelpTextWithSync (2364665535969139880) -->
+ <skip />
+ <!-- no translation found for noContactsHelpTextWithSync (3017521127042216243) -->
+ <skip />
+ <!-- no translation found for noContactsNoSimHelpText (6031363021287849874) -->
+ <skip />
+ <!-- no translation found for noContactsNoSimHelpText (467658807711582876) -->
+ <skip />
+ <!-- no translation found for noContactsNoSimHelpTextWithSync (6222739731808897565) -->
+ <skip />
+ <!-- no translation found for noContactsNoSimHelpTextWithSync (9040060730467973050) -->
+ <skip />
+ <!-- no translation found for noFavoritesHelpText (3744655776704833277) -->
+ <skip />
+ <!-- no translation found for liveFolder_all_label (5961411940473276616) -->
+ <skip />
+ <string name="liveFolder_favorites_label" msgid="2674341514070517105">"Dibintangkan"</string>
+ <string name="liveFolder_phones_label" msgid="1709786878793436245">"Telefon"</string>
+ <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Gunakan pad kekunci nada sentuh"</string>
+ <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Kembali ke panggilan yang sedang berlangsung"</string>
+ <string name="dialer_addAnotherCall" msgid="4205688819890074468">"Tambah panggilan"</string>
+ <string name="callDetailTitle" msgid="5340227785196217938">"Butiran panggilan"</string>
+ <string name="toast_call_detail_error" msgid="7200975244804730096">"Tidak boleh membaca butiran untuk panggilan yang diminta."</string>
+ <string name="type_incoming" msgid="6502076603836088532">"Panggilan masuk"</string>
+ <string name="type_outgoing" msgid="343108709599392641">"Panggilan keluar"</string>
+ <string name="type_missed" msgid="2720502601640509542">"Panggilan tidak dijawab"</string>
+ <string name="actionIncomingCall" msgid="6028930669817038600">"Panggilan masuk"</string>
+ <string name="callBack" msgid="5498224409038809224">"Panggil balik"</string>
+ <string name="callAgain" msgid="3197312117049874778">"Panggil semula"</string>
+ <string name="returnCall" msgid="8171961914203617813">"Balas panggilan"</string>
+ <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> min <xliff:g id="SECONDS">%s</xliff:g> saat"</string>
+ <!-- no translation found for favoritesFrquentSeparator (8107518433381283736) -->
+ <skip />
+ <!-- no translation found for add_contact_dlg_title (2896685845822146494) -->
+ <skip />
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Tambah \"<xliff:g id="EMAIL">%s</xliff:g>\" kepada kenalan?"</string>
+ <string name="description_image_button_one" msgid="1740638037139856139">"satu"</string>
+ <string name="description_image_button_two" msgid="5882638439003731308">"dua"</string>
+ <string name="description_image_button_three" msgid="8709731759376015180">"tiga"</string>
+ <string name="description_image_button_four" msgid="3530239685642246130">"empat"</string>
+ <string name="description_image_button_five" msgid="1182465427501188413">"lima"</string>
+ <string name="description_image_button_six" msgid="2093656269261415475">"enam"</string>
+ <string name="description_image_button_seven" msgid="2450357020447676481">"tujuh"</string>
+ <string name="description_image_button_eight" msgid="6969435115163287801">"lapan"</string>
+ <string name="description_image_button_nine" msgid="7857248695662558323">"sembilan"</string>
+ <string name="description_image_button_star" msgid="3365919907520767866">"bintang"</string>
+ <string name="description_image_button_zero" msgid="4133108949401820710">"sifar"</string>
+ <string name="description_image_button_pound" msgid="3039765597595889230">"paun"</string>
+ <!-- no translation found for description_voicemail_button (3402506823655455591) -->
+ <skip />
+ <!-- no translation found for description_dial_button (1274091017188142646) -->
+ <skip />
+ <!-- no translation found for description_delete_button (6263102114033407382) -->
+ <skip />
+ <!-- no translation found for description_digits_edittext (8760207516497016437) -->
+ <skip />
+ <!-- no translation found for description_contact_photo (3387458082667894062) -->
+ <skip />
+ <!-- no translation found for description_minus_button (387136707700230172) -->
+ <skip />
+ <!-- no translation found for description_plus_button (515164827856229880) -->
+ <skip />
+ <!-- no translation found for no_sdcard_title (8543619259870877473) -->
+ <skip />
+ <!-- no translation found for no_sdcard_title (5911758680339949273) -->
+ <skip />
+ <!-- no translation found for no_sdcard_message (1334170151822669976) -->
+ <skip />
+ <!-- no translation found for no_sdcard_message (6019391476490445358) -->
+ <skip />
+ <!-- no translation found for searching_vcard_title (4970508055399376813) -->
+ <skip />
+ <!-- no translation found for import_from_sim (3859272228033941659) -->
+ <skip />
+ <!-- no translation found for import_from_sdcard (8668347930577565175) -->
+ <skip />
+ <!-- no translation found for import_from_sdcard (8550360976693202816) -->
+ <skip />
+ <!-- no translation found for export_to_sdcard (6092815580965201089) -->
+ <skip />
+ <!-- no translation found for export_to_sdcard (2597105442616166277) -->
+ <skip />
+ <!-- no translation found for share_visible_contacts (890150378880783797) -->
+ <skip />
+ <!-- no translation found for import_one_vcard_string (9059163467020328433) -->
+ <skip />
+ <!-- no translation found for import_multiple_vcard_string (3810226492811062392) -->
+ <skip />
+ <!-- no translation found for import_all_vcard_string (5518136113853448474) -->
+ <skip />
+ <!-- no translation found for searching_vcard_message (996170203695743981) -->
+ <skip />
+ <!-- no translation found for searching_vcard_message (6917522333561434546) -->
+ <skip />
+ <!-- no translation found for scanning_sdcard_failed_title (6957414493948497249) -->
+ <skip />
+ <!-- no translation found for scanning_sdcard_failed_title (3506782007953167180) -->
+ <skip />
+ <!-- no translation found for scanning_sdcard_failed_message (4106156155205860626) -->
+ <skip />
+ <!-- no translation found for scanning_sdcard_failed_message (3761992500690182922) -->
+ <skip />
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"Ralat I/O"</string>
+ <!-- no translation found for fail_reason_low_memory_during_import (7514918659342886381) -->
+ <skip />
+ <!-- no translation found for fail_reason_vcard_parse_error (1201233722762680214) -->
+ <skip />
+ <!-- no translation found for fail_reason_not_supported (294499264620201243) -->
+ <skip />
+ <!-- no translation found for vcard_import_failed (7718330063493653085) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (6339234836196984924) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (1730986357514922756) -->
+ <skip />
+ <!-- no translation found for fail_reason_failed_to_collect_vcard_meta_info (4154492282316067754) -->
+ <skip />
+ <!-- no translation found for fail_reason_failed_to_read_files (3659521123567134029) -->
+ <skip />
+ <!-- no translation found for fail_reason_unknown (999034019513096768) -->
+ <skip />
+ <!-- no translation found for select_vcard_title (3968948173786172468) -->
+ <skip />
+ <!-- no translation found for caching_vcard_title (5009556022082659780) -->
+ <skip />
+ <!-- no translation found for caching_vcard_message (2380844718093378900) -->
+ <skip />
+ <!-- no translation found for progress_notifier_message (2311011466908220528) -->
+ <skip />
+ <!-- no translation found for importing_vcard_description (4245275224298571351) -->
+ <skip />
+ <!-- no translation found for reading_vcard_failed_title (2162610359561887043) -->
+ <skip />
+ <!-- no translation found for reading_vcard_canceled_title (1770608329958463131) -->
+ <skip />
+ <!-- no translation found for importing_vcard_finished_title (3341541727268747967) -->
+ <skip />
+ <!-- no translation found for importing_vcard_canceled_title (6367906965439777280) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message (2804911199145873396) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message_with_default_name (1022969530654129470) -->
+ <skip />
+ <!-- no translation found for vcard_import_request_rejected_message (2592424820635325951) -->
+ <skip />
+ <!-- no translation found for vcard_export_will_start_message (2210241345252081463) -->
+ <skip />
+ <!-- no translation found for vcard_export_request_rejected_message (8259494002258326330) -->
+ <skip />
+ <!-- no translation found for vcard_unknown_filename (7171709890959915954) -->
+ <skip />
+ <!-- no translation found for percentage (34897865327092209) -->
+ <skip />
+ <!-- no translation found for confirm_export_title (7648747763127442983) -->
+ <skip />
+ <!-- no translation found for confirm_export_message (3875683519257829750) -->
+ <skip />
+ <!-- no translation found for exporting_contact_failed_title (585823094820602526) -->
+ <skip />
+ <!-- no translation found for exporting_contact_failed_message (4151348002470298092) -->
+ <skip />
+ <!-- no translation found for fail_reason_no_exportable_contact (4919714086648344495) -->
+ <skip />
+ <!-- no translation found for fail_reason_too_many_vcard (3745507837635270265) -->
+ <skip />
+ <!-- no translation found for fail_reason_too_many_vcard (7084146295639672658) -->
+ <skip />
+ <!-- no translation found for fail_reason_too_long_filename (1915716071321839166) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_finished_title (4259736138838583213) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_canceled_title (1827672399438062140) -->
+ <skip />
+ <string name="exporting_contact_list_title" msgid="9072240631534457415">"Mengeksport data kenalan"</string>
+ <string name="exporting_contact_list_message" msgid="5640326540405486055">"Mengeksport data kenalan ke \"<xliff:g id="FILE_NAME">%s</xliff:g>\""</string>
+ <string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">"Tidak boleh memulakan pengeksport: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"Ralat berlaku semasa mengeksport: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <!-- no translation found for composer_failed_to_get_database_infomation (3723109558155169053) -->
+ <skip />
+ <!-- no translation found for composer_has_no_exportable_contact (5161491059051198932) -->
+ <skip />
+ <!-- no translation found for composer_has_no_exportable_contact (322344221706924358) -->
+ <skip />
+ <!-- no translation found for composer_not_initialized (8041534450748388843) -->
+ <skip />
+ <string name="fail_reason_could_not_open_file" msgid="4013520943128739511">"Tidak dapat membuka \"<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> daripada <xliff:g id="TOTAL_NUMBER">%s</xliff:g> kenalan"</string>
+ <!-- no translation found for cancel_import_confirmation_title (5578683596010294836) -->
+ <skip />
+ <!-- no translation found for cancel_import_confirmation_message (8560937090143057107) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_title (6516467140276768528) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_message (1392976902396351957) -->
+ <skip />
+ <!-- no translation found for cancel_vcard_import_or_export_failed (7096533244663846810) -->
+ <skip />
+ <!-- no translation found for search_settings_description (2675223022992445813) -->
+ <skip />
+ <!-- no translation found for add_2sec_pause (9214012315201040129) -->
+ <skip />
+ <!-- no translation found for add_wait (3360818652790319634) -->
+ <skip />
+ <!-- no translation found for call_disambig_title (1911302597959335178) -->
+ <skip />
+ <!-- no translation found for sms_disambig_title (4675399294513152364) -->
+ <skip />
+ <!-- no translation found for make_primary (5829291915305113983) -->
+ <skip />
+ <!-- no translation found for quickcontact_missing_app (4600366393134289038) -->
+ <skip />
+ <!-- no translation found for quickcontact_remember_choice (5964536411579749424) -->
+ <skip />
+ <!-- no translation found for quickcontact_missing_name (5590266114306996632) -->
+ <skip />
+ <!-- no translation found for quickcontact_no_data (2098000859125253675) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_description (3792792870662989100) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_caption (4287306111861545753) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_button (8728754360205289059) -->
+ <skip />
+ <!-- no translation found for menu_accounts (8499114602017077970) -->
+ <skip />
+ <!-- no translation found for menu_import_export (3765725645491577190) -->
+ <skip />
+ <!-- no translation found for dialog_import_export (4771877268244096596) -->
+ <skip />
+ <!-- no translation found for menu_share (8746849630474240344) -->
+ <skip />
+ <!-- no translation found for share_via (563121028023030093) -->
+ <skip />
+ <!-- no translation found for share_error (4374508848981697170) -->
+ <skip />
+ <!-- no translation found for nameLabelsGroup (2034640839640477827) -->
+ <skip />
+ <!-- no translation found for nicknameLabelsGroup (2891682101053358010) -->
+ <skip />
+ <!-- no translation found for organizationLabelsGroup (2478611760751832035) -->
+ <skip />
+ <!-- no translation found for websiteLabelsGroup (4202998982804009261) -->
+ <skip />
+ <!-- no translation found for eventLabelsGroup (8069912895912714412) -->
+ <skip />
+ <!-- no translation found for relationLabelsGroup (1854373894284572781) -->
+ <skip />
+ <!-- no translation found for groupsLabel (8573535366319059326) -->
+ <skip />
+ <!-- no translation found for type_short_home (7770424864090605384) -->
+ <skip />
+ <!-- no translation found for type_short_mobile (1655473281466676216) -->
+ <skip />
+ <!-- no translation found for type_short_work (4925330752504537861) -->
+ <skip />
+ <!-- no translation found for type_short_pager (2613818970827594238) -->
+ <skip />
+ <!-- no translation found for type_short_other (5669407180177236769) -->
+ <skip />
+ <!-- no translation found for dialog_new_contact_account (9044704073286262197) -->
+ <skip />
+ <!-- no translation found for menu_sync_remove (3266725887008450161) -->
+ <skip />
+ <!-- no translation found for dialog_sync_add (8267045393119375803) -->
+ <skip />
+ <!-- no translation found for display_more_groups (2682547080423434170) -->
+ <skip />
+ <!-- no translation found for display_ungrouped (4602580795576261158) -->
+ <skip />
+ <!-- no translation found for display_all_contacts (6846131371214707956) -->
+ <skip />
+ <!-- no translation found for display_warn_remove_ungrouped (2314043155909167610) -->
+ <skip />
+ <!-- no translation found for account_phone (7946049152658522054) -->
+ <skip />
+ <!-- no translation found for account_phone (3682950835276226870) -->
+ <skip />
+ <!-- no translation found for call_custom (7756571794763171802) -->
+ <skip />
+ <!-- no translation found for call_home (1990519474420545392) -->
+ <skip />
+ <!-- no translation found for call_mobile (7502236805487609178) -->
+ <skip />
+ <!-- no translation found for call_work (5328785911463744028) -->
+ <skip />
+ <!-- no translation found for call_fax_work (7467763592359059243) -->
+ <skip />
+ <!-- no translation found for call_fax_home (8342175628887571876) -->
+ <skip />
+ <!-- no translation found for call_pager (9003902812293983281) -->
+ <skip />
+ <!-- no translation found for call_other (8563753966926932052) -->
+ <skip />
+ <!-- no translation found for call_callback (1910165691349426858) -->
+ <skip />
+ <!-- no translation found for call_car (3280537320306436445) -->
+ <skip />
+ <!-- no translation found for call_company_main (6105120947138711257) -->
+ <skip />
+ <!-- no translation found for call_isdn (1541590690193403411) -->
+ <skip />
+ <!-- no translation found for call_main (6082900571803441339) -->
+ <skip />
+ <!-- no translation found for call_other_fax (5745314124619636674) -->
+ <skip />
+ <!-- no translation found for call_radio (8296755876398357063) -->
+ <skip />
+ <!-- no translation found for call_telex (2223170774548648114) -->
+ <skip />
+ <!-- no translation found for call_tty_tdd (8951266948204379604) -->
+ <skip />
+ <!-- no translation found for call_work_mobile (8707874281430105394) -->
+ <skip />
+ <!-- no translation found for call_work_pager (3419348514157949008) -->
+ <skip />
+ <!-- no translation found for call_assistant (2141641383068514308) -->
+ <skip />
+ <!-- no translation found for call_mms (6274041545876221437) -->
+ <skip />
+ <!-- no translation found for sms_custom (5932736853732191825) -->
+ <skip />
+ <!-- no translation found for sms_home (7524332261493162995) -->
+ <skip />
+ <!-- no translation found for sms_mobile (5200107250451030769) -->
+ <skip />
+ <!-- no translation found for sms_work (2269624156655267740) -->
+ <skip />
+ <!-- no translation found for sms_fax_work (8028189067816907075) -->
+ <skip />
+ <!-- no translation found for sms_fax_home (9204042076306809634) -->
+ <skip />
+ <!-- no translation found for sms_pager (7730404569637015192) -->
+ <skip />
+ <!-- no translation found for sms_other (806127844607642331) -->
+ <skip />
+ <!-- no translation found for sms_callback (5004824430094288752) -->
+ <skip />
+ <!-- no translation found for sms_car (7444227058437359641) -->
+ <skip />
+ <!-- no translation found for sms_company_main (118970873419678087) -->
+ <skip />
+ <!-- no translation found for sms_isdn (8153785037515047845) -->
+ <skip />
+ <!-- no translation found for sms_main (8621625784504541679) -->
+ <skip />
+ <!-- no translation found for sms_other_fax (3888842199855843152) -->
+ <skip />
+ <!-- no translation found for sms_radio (3329166673433967820) -->
+ <skip />
+ <!-- no translation found for sms_telex (9034802430065267848) -->
+ <skip />
+ <!-- no translation found for sms_tty_tdd (6782284969132531532) -->
+ <skip />
+ <!-- no translation found for sms_work_mobile (2459939960512702560) -->
+ <skip />
+ <!-- no translation found for sms_work_pager (5566924423316960597) -->
+ <skip />
+ <!-- no translation found for sms_assistant (2773424339923116234) -->
+ <skip />
+ <!-- no translation found for sms_mms (4069352461380762677) -->
+ <skip />
+ <!-- no translation found for email_home (8573740658148184279) -->
+ <skip />
+ <!-- no translation found for email_mobile (2042889209787989814) -->
+ <skip />
+ <!-- no translation found for email_work (2807430017302722689) -->
+ <skip />
+ <!-- no translation found for email_other (3454004077967657109) -->
+ <skip />
+ <!-- no translation found for email_custom (7548003991586214105) -->
+ <skip />
+ <!-- no translation found for email (5668400997660065897) -->
+ <skip />
+ <!-- no translation found for map_home (1243547733423343982) -->
+ <skip />
+ <!-- no translation found for map_work (1360474076921878088) -->
+ <skip />
+ <!-- no translation found for map_other (3817820803587012641) -->
+ <skip />
+ <!-- no translation found for map_custom (6184363799976265281) -->
+ <skip />
+ <!-- no translation found for chat_aim (2588492205291249142) -->
+ <skip />
+ <!-- no translation found for chat_msn (8041633440091073484) -->
+ <skip />
+ <!-- no translation found for chat_yahoo (6629211142719943666) -->
+ <skip />
+ <!-- no translation found for chat_skype (1210045020427480566) -->
+ <skip />
+ <!-- no translation found for chat_qq (4294637812847719693) -->
+ <skip />
+ <!-- no translation found for chat_gtalk (981575737258117697) -->
+ <skip />
+ <!-- no translation found for chat_icq (8438405386153745775) -->
+ <skip />
+ <!-- no translation found for chat_jabber (7561444230307829609) -->
+ <skip />
+ <!-- no translation found for chat (9025361898797412245) -->
+ <skip />
+ <!-- no translation found for postal_address (8765560217149624536) -->
+ <skip />
+ <!-- no translation found for postal_street (8133143961580058972) -->
+ <skip />
+ <!-- no translation found for postal_pobox (4431938829180269821) -->
+ <skip />
+ <!-- no translation found for postal_neighborhood (1450783874558956739) -->
+ <skip />
+ <!-- no translation found for postal_city (6597491300084895548) -->
+ <skip />
+ <!-- no translation found for postal_region (6045263193478437672) -->
+ <skip />
+ <!-- no translation found for postal_postcode (572136414136673751) -->
+ <skip />
+ <!-- no translation found for postal_country (7638264508416368690) -->
+ <skip />
+ <!-- no translation found for full_name (6602579550613988977) -->
+ <skip />
+ <!-- no translation found for name_given (1687286314106019813) -->
+ <skip />
+ <!-- no translation found for name_family (3416695586119999058) -->
+ <skip />
+ <!-- no translation found for name_prefix (59756378548779822) -->
+ <skip />
+ <!-- no translation found for name_middle (8467433655992690326) -->
+ <skip />
+ <!-- no translation found for name_suffix (3855278445375651441) -->
+ <skip />
+ <!-- no translation found for name_phonetic_given (6853570431394449191) -->
+ <skip />
+ <!-- no translation found for name_phonetic_middle (8643721493320405200) -->
+ <skip />
+ <!-- no translation found for name_phonetic_family (462095502140180305) -->
+ <skip />
+ <!-- no translation found for name_phonetic (4259595234312430484) -->
+ <skip />
+ <!-- no translation found for account_type_format (718948015590343010) -->
+ <skip />
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
+ <!-- no translation found for use_photo_as_primary (8807110122951157246) -->
+ <skip />
+ <!-- no translation found for contact_read_only (1203216914575723978) -->
+ <skip />
+ <!-- no translation found for no_contact_details (6754415338321837001) -->
+ <skip />
+ <!-- no translation found for display_options_sort_list_by (6080091755852211076) -->
+ <skip />
+ <!-- no translation found for display_options_sort_by_given_name (184916793466387067) -->
+ <skip />
+ <!-- no translation found for display_options_sort_by_family_name (7857986975275712622) -->
+ <skip />
+ <!-- no translation found for display_options_view_names_as (18022868169627979) -->
+ <skip />
+ <!-- no translation found for display_options_view_given_name_first (6968288511197363292) -->
+ <skip />
+ <!-- no translation found for display_options_view_family_name_first (1447288164951453714) -->
+ <skip />
+ <!-- no translation found for search_bar_hint (1012756309632856553) -->
+ <skip />
+ <!-- no translation found for search_for_all_contacts (6644963335787294131) -->
+ <skip />
+ <!-- no translation found for take_photo (7496128293167402354) -->
+ <skip />
+ <!-- no translation found for take_new_photo (7341354729436576304) -->
+ <skip />
+ <!-- no translation found for pick_photo (448886509158039462) -->
+ <skip />
+ <!-- no translation found for pick_new_photo (7962368009197147617) -->
+ <skip />
+ <!-- no translation found for locale_change_in_progress (7583992153091537467) -->
+ <skip />
+ <!-- no translation found for upgrade_in_progress (474511436863451061) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory (6153384328042175667) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory_uninstall (1721798828992091432) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory_retry (8431289830472724609) -->
+ <skip />
+ <!-- no translation found for search_results_searching (7755623475227227314) -->
+ <skip />
+ <!-- no translation found for menu_display_selected (6470001164297969034) -->
+ <skip />
+ <!-- no translation found for menu_display_all (8887488642609786198) -->
+ <skip />
+ <!-- no translation found for menu_select_all (621719255150713545) -->
+ <skip />
+ <!-- no translation found for menu_select_none (7093222469852132345) -->
+ <skip />
+ <!-- no translation found for multiple_picker_title:one (4761009734586319101) -->
+ <!-- no translation found for multiple_picker_title:other (4608837420986126229) -->
+ <!-- no translation found for no_contacts_selected (5877803471037324613) -->
+ <skip />
+ <!-- no translation found for add_field (2384260056674995230) -->
+ <skip />
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
+ <!-- no translation found for contact_status_update_attribution (752179367353018597) -->
+ <skip />
+ <!-- no translation found for contact_status_update_attribution_with_date (7358045508107825068) -->
+ <skip />
+ <!-- no translation found for description_star (2605854427360036550) -->
+ <skip />
+ <!-- no translation found for edit_contact (7529281274005689512) -->
+ <skip />
+ <!-- no translation found for merge_info:one (148365587896371969) -->
+ <!-- no translation found for merge_info:other (425683718017380845) -->
+ <!-- no translation found for local_invisible_directory (6046691709127661065) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_title (5276699501316246253) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_message (3842757977671434836) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_title (1064042382692091314) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_message (6549585283910518095) -->
+ <skip />
+ <!-- no translation found for menu_copyContact (4401683725471696686) -->
+ <skip />
+ <!-- no translation found for contact_directory_description (683398073603909119) -->
+ <skip />
+ <!-- no translation found for search_label (6789295859496641042) -->
+ <skip />
+ <!-- no translation found for directory_search_label (1887759056597975053) -->
+ <skip />
+ <!-- no translation found for local_search_label (1686089693064201315) -->
+ <skip />
+ <!-- no translation found for toast_making_personal_copy (7905283986345263275) -->
+ <skip />
+ <!-- no translation found for list_filter_prompt (7481426622828055116) -->
+ <skip />
+ <!-- no translation found for list_filter_all_accounts (8908683398914322369) -->
+ <skip />
+ <!-- no translation found for list_filter_all_starred (5031734941601931356) -->
+ <skip />
+ <!-- no translation found for list_filter_custom (8910173055702057002) -->
+ <skip />
+ <!-- no translation found for list_filter_customize (2035084418635775579) -->
+ <skip />
+ <!-- no translation found for list_filter_phones (7905045603593508221) -->
+ <skip />
+ <!-- no translation found for list_filter_single (5871400283515893087) -->
+ <skip />
+ <!-- no translation found for custom_list_filter (7836035257402013957) -->
+ <skip />
+ <!-- no translation found for activity_title_settings (5464130076132770781) -->
+ <skip />
+ <!-- no translation found for menu_settings (377929915873428211) -->
+ <skip />
+ <!-- no translation found for preference_displayOptions (1341720270148252393) -->
+ <skip />
+ <!-- no translation found for organization_company_and_title (6718207751363732025) -->
+ <skip />
+ <!-- no translation found for hint_findContacts (1808681193458772072) -->
+ <skip />
+ <!-- no translation found for non_phone_caption (1541655052330027380) -->
+ <skip />
+ <!-- no translation found for non_phone_add_to_contacts (6590985286250471169) -->
+ <skip />
+ <!-- no translation found for non_phone_close (7608506439725515667) -->
+ <skip />
+ <!-- no translation found for widget_name_and_phonetic (8739586586600099979) -->
+ <skip />
+ <!-- no translation found for date_year_toggle (7356532842767854606) -->
+ <skip />
+ <!-- no translation found for social_widget_label (6378905543028924592) -->
+ <skip />
+ <!-- no translation found for social_widget_loading (3697996166985327861) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_create_contact (7014525713871959208) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_add_account (7911101713860139754) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_import_contacts (4456440183590517471) -->
+ <skip />
+ <!-- no translation found for create_group_dialog_title (6874527142828424475) -->
+ <skip />
+ <!-- no translation found for create_group_item_label (5218022006186243310) -->
+ <skip />
+ <!-- no translation found for rename_group_dialog_title (3765299704290513289) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_title (7368429698398624427) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_message (295063284548750881) -->
+ <skip />
+ <!-- no translation found for toast_join_with_empty_contact (5015189525953438968) -->
+ <skip />
+ <!-- no translation found for indicator_joined_contact (3321049349627022128) -->
+ <skip />
+ <!-- no translation found for toast_text_copied (5143776250008541719) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_title (3950463632415908534) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_message (7021968394611740251) -->
+ <skip />
+ <!-- no translation found for discard (1234315037371251414) -->
+ <skip />
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 23e536d..6fc2e5b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Standardvalg"</string>
<string name="removePhoto" msgid="4898105274130284565">"Fjern bilde"</string>
<string name="noContacts" msgid="8579310973261953559">"Ingen kontakter."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Ingen grupper."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Fant ingen kontakter."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Ingen kontakter med telefonnummer."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Kun kontakter med telefon"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> funnet"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakter"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupper"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritter"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Logg"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Anropsloggen er tom."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Tøm samtalelogg"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Er du sikker på at du vil tømme samtaleloggen?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Tømming av anropslogg"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Telefonsvarer"</string>
@@ -161,12 +164,12 @@
<string name="simContacts_title" msgid="27341688347689769">"Kontakter på SIM-kort"</string>
<string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"Du har ingen kontakter å vise. (Hvis du nettopp har lagt til en konto, kan det ta noen minutter å synkronisere kontaktene.)"</string>
<string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">"Du har ingen kontakter å vise."</string>
- <!-- syntax error in translation for noContactsHelpText (6450346791169710787) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:292 in java.io.StringReader@46ae506e) -->
- <!-- syntax error in translation for noContactsHelpText (7633826236417884130) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:293 in java.io.StringReader@5e228a02) -->
+ <!-- syntax error in translation for noContactsHelpText (6450346791169710787) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:292 in java.io.StringReader@35a8767) -->
+ <!-- syntax error in translation for noContactsHelpText (7633826236417884130) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:293 in java.io.StringReader@2c6f7ce9) -->
<string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"Du har ingen kontakter å vise. (Hvis du nylig la til en konto, kan det ta noen minutter å synkronisere kontaktene.)"\n\n"Slik legger du til kontakter: Trykk på "<font fgcolor="#ffffffff"><b>"Meny"</b></font>", og trykk deretter på:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Kontoer"</b></font>" for å legge til eller konfigurere en konto med kontakter som kan synkroniseres til nettbrettet"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Visningsalternativer"</b></font>" for å endre hvilke kontakter som vises"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ny kontakt"</b></font>" for å opprette en ny kontakt fra grunnen av"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/Eksporter"</b></font>" for å importere kontakter fra SIM- eller SD-kort"\n</li></string>
<string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"Du har ingen kontakter å vise. (Hvis du nylig la til en konto, kan det ta noen minutter å synkronisere kontaktene.)"\n\n"Slik legger du til kontakter: Trykk på "<font fgcolor="#ffffffff"><b>"Meny"</b></font>" og trykk deretter på: "\n" "\n<li><font fgcolor="#ffffffff"><b>"Kontoer "</b></font>" for å legge til eller konfigurere en konto med kontakter som kan synkroniseres til telefonen"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Visningsalternativer"</b></font>" for å endre hvilke kontakter som vises"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ny kontakt"</b></font>" for å opprette en ny kontakt"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importér/Eksportér"</b></font>" for å importere kontakter fra SIM- eller SD-kort"\n</li></string>
- <!-- syntax error in translation for noContactsNoSimHelpText (6031363021287849874) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:297 in java.io.StringReader@2d92b996) -->
- <!-- syntax error in translation for noContactsNoSimHelpText (467658807711582876) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:297 in java.io.StringReader@7bd63e39) -->
+ <!-- syntax error in translation for noContactsNoSimHelpText (6031363021287849874) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:297 in java.io.StringReader@4b71bbc9) -->
+ <!-- syntax error in translation for noContactsNoSimHelpText (467658807711582876) org.xmlpull.v1.XmlPullParserException: expected: /li read: font (position:END_TAG </font>@1:297 in java.io.StringReader@17dfafd1) -->
<string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"Du har ingen kontakter å vise. (Hvis du nylig la til en konto, kan det ta noen minutter å synkronisere kontaktene.)"\n\n"Slik legger du til kontakter: Trykk på "<font fgcolor="#ffffffff"><b>"Meny"</b></font>", og trykk deretter på: "\n" "\n<li><font fgcolor="#ffffffff"><b>"Kontoer"</b></font>" for å legge til eller konfigurere en konto med kontakter som kan synkroniseres til nettbrettet"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Visningsalternativer"</b></font>" for å endre hvilke kontakter som vises"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ny kontakt"</b></font>" for å opprette en ny kontakt fra grunnen av"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importer/eksporter"</b></font>" for å importere kontakter fra SD-kortet"\n</li></string>
<string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"Du har ingen kontakter å vise. (Hvis du nylig la til en konto, kan det ta noen minutter å synkronisere kontaktene.)"\n\n"Slik legger du til kontakter: Trykk på "<font fgcolor="#ffffffff"><b>"Meny"</b></font>" og trykk deretter på: "\n" "\n<li><font fgcolor="#ffffffff"><b>"Kontoer "</b></font>" for å legge til eller konfigurere en konto med kontakter som kan synkroniseres til telefonen"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Visningsalternativer"</b></font>" for å endre hvilke kontakter som vises"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ny kontakt"</b></font>" for å opprette en ny kontakt"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Importér/eksportér"</b></font>" for å importere kontakter fra SD-kortet"\n</li></string>
<string name="noFavoritesHelpText" msgid="3744655776704833277">"Du har ingen favoritter."\n\n"Slik legger du til en kontakt i favorittlisten:"\n\n" "<li>"Trykk på fanen "<b>"Kontakter"</b>" "\n</li>" "\n<li>"Trykk på kontakten du vil legge til i favoritter"\n</li>" "\n<li>"Trykk på stjernen ved siden av kontaktnavnet"\n</li></string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Fant ikke noe minnekort"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Leter etter VCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importér fra SIM-kort"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importér fra lagring"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Eksportér til lagring"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importér fra lagring"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importér fra minnekort"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Eksportér til lagring"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Eksportér til minnekort"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Del synlige kontakter"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importer én VCard-fil"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importer flere vCard-filer"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetisk etternavn"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetisk navn"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g>-kontakt"</string>
- <string name="from_account_format" msgid="687567483928582084">"fra <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Bruk dette bildet"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g>-kontaktinformasjon kan ikke redigeres på denne enheten."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Ingen utfyllende informasjon for denne kontakten"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Ingen kontakter valgt."</string>
<string name="add_field" msgid="2384260056674995230">"Legg til et annet felt"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Legg til nytt tlf.nr."</string>
+ <string name="add_email" msgid="175079666329862215">"Legg til ny e-post"</string>
+ <string name="add_im" msgid="5158094627521120439">"Legg til nettpratkonto"</string>
+ <string name="add_address" msgid="418292312672970688">"Legg til ny adresse"</string>
+ <string name="add_note" msgid="2753771325725383279">"Legg til ny merknad:"</string>
+ <string name="add_website" msgid="4312391288948517344">"Legg til nytt nettsted"</string>
+ <string name="add_event" msgid="7488781591843886426">"Legg til ny aktivitet"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Legg til nytt forhold"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favoritt"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index d4d56db..eca229f 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Standaard"</string>
<string name="removePhoto" msgid="4898105274130284565">"Foto verwijderen"</string>
<string name="noContacts" msgid="8579310973261953559">"Geen contacten."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Geen groepen."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Kan geen overeenkomende contacten vinden."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Geen contacten met telefoonnummers."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Alleen contacten met tel.nr."</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> gevonden"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contact"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Groepen"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoriet"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefoon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Gesprek"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Gesprekken is leeg"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Oproeplogboek wissen"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Weet u zeker dat u het oproeplogboek wilt wissen?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Oproeplogboek wissen"</string>
<string name="imei" msgid="3045126336951684285">"IMEI-nummer"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Voicemail"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Geen SD-kaart gedetecteerd"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Zoeken naar vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importeren van SIM-kaart"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importeren uit opslag"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exporteren naar opslag"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importeren uit opslag"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importeren van SD-kaart"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exporteren naar opslag"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exporteren naar SD-kaart"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Zichtbare contacten delen"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Eén vCard-bestand importeren"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Meerdere vCard-bestanden importeren"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetische achternaam"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetisch gespelde naam"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> contact"</string>
- <string name="from_account_format" msgid="687567483928582084">"van <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Deze foto gebruiken"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Contactgegevens van <xliff:g id="SOURCE">%1$s</xliff:g> kunnen niet worden bewerkt op dit apparaat."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Geen extra gegevens voor dit contact"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Geen contacten geselecteerd."</string>
<string name="add_field" msgid="2384260056674995230">"Nog een veld toevoegen"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Nieuw telefoonnummer"</string>
+ <string name="add_email" msgid="175079666329862215">"Nieuw e-mailadres"</string>
+ <string name="add_im" msgid="5158094627521120439">"Nieuw IM-account"</string>
+ <string name="add_address" msgid="418292312672970688">"Nieuw adres"</string>
+ <string name="add_note" msgid="2753771325725383279">"Nieuwe opmerking"</string>
+ <string name="add_website" msgid="4312391288948517344">"Nieuwe website"</string>
+ <string name="add_event" msgid="7488781591843886426">"Nieuwe gebeurtenis"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Nieuwe relatie"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favoriet"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 98e3eff..f1d5b5d 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Domyślny"</string>
<string name="removePhoto" msgid="4898105274130284565">"Usuń zdjęcie"</string>
<string name="noContacts" msgid="8579310973261953559">"Brak kontaktów"</string>
+ <string name="noGroups" msgid="8614664663561385253">"Brak grup."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nie znaleziono pasujących kontaktów."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Brak kontaktów z numerami telefonów"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Tylko kontakty z telefonami"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Znaleziono: <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakty"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupy"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Ulubione"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Rejestr"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Rejestr połączeń jest pusty."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Wyczyść rejestr połączeń"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Czy na pewno chcesz wyczyścić rejestr połączeń?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Czyszczenie dziennika połączeń"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"Numer MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Poczta głosowa"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nie wykryto karty SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Wyszukiwanie danych vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importuj z karty SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importuj z nośnika"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Eksportuj na nośnik"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importuj z nośnika"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importuj z karty SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Eksportuj na nośnik"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Eksportuj na kartę SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Udostępnij widoczne kontakty"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importuj jeden plik vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importuj wiele plików vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Nazwisko (fonetycznie)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nazwisko (fonetycznie)"</string>
<string name="account_type_format" msgid="718948015590343010">"Kontakt <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"z <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Użyj tego zdjęcia"</string>
<string name="contact_read_only" msgid="1203216914575723978">"W tym urządzeniu nie można edytować informacji kontaktowych <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Brak dodatkowych informacji dla tego kontaktu"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nie wybrano kontaktów."</string>
<string name="add_field" msgid="2384260056674995230">"Dodaj inne pole"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Dodaj nowy nr telefonu"</string>
+ <string name="add_email" msgid="175079666329862215">"Dodaj nowy e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Dodaj nowe konto IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Dodaj nowy adres"</string>
+ <string name="add_note" msgid="2753771325725383279">"Dodaj nową notatkę"</string>
+ <string name="add_website" msgid="4312391288948517344">"Dodaj nową witrynę"</string>
+ <string name="add_event" msgid="7488781591843886426">"Dodaj nowe wydarzenie"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Dodaj nową relację"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"za pośrednictwem: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>, za pośrednictwem: <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"ulubione"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 5de83ef..5b258f1 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predefinido"</string>
<string name="removePhoto" msgid="4898105274130284565">"Remover fotografia"</string>
<string name="noContacts" msgid="8579310973261953559">"Sem contactos."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nenhum grupo."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Não foram encontrados contactos correspondentes."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Sem contactos com números de telefone."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Apenas contactos com telefones"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> encontrado(s)"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contactos"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupos"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritos"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefone"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Chamadas"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"O registo de chamadas está vazio."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Limpar registo de chamadas"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Tem a certeza de que pretende limpar o registo de chamadas?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Limpar registo de chamadas"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Correio de voz"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Não foi detectado nenhum cartão SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"A procurar vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importar do cartão SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importar do armazenamento"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportar para o armazen."</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importar do armazenamento"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importar do cartão SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportar para o armazen."</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportar para cartão SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Partilhar contactos visíveis"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importar um ficheiro VCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importar vários ficheiros vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonética do segundo apelido"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nome fonético"</string>
<string name="account_type_format" msgid="718948015590343010">"Contacto de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilizar esta fotografia"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Não é possível editar as informações de contacto do <xliff:g id="SOURCE">%1$s</xliff:g> neste dispositivo."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Não há informações adicionais para este contacto"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nenhum contacto seleccionado."</string>
<string name="add_field" msgid="2384260056674995230">"Adicionar outro campo"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Adic. novo n.º telef."</string>
+ <string name="add_email" msgid="175079666329862215">"Adicionar novo e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Adic. nova conta MI"</string>
+ <string name="add_address" msgid="418292312672970688">"Adicionar novo endereço"</string>
+ <string name="add_note" msgid="2753771325725383279">"Adicionar nova nota"</string>
+ <string name="add_website" msgid="4312391288948517344">"Adicionar novo site"</string>
+ <string name="add_event" msgid="7488781591843886426">"Adicionar novo evento"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Adicionar nova relação"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"através do <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> através do <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorito"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 4bf8625..fc8e847 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Padrão"</string>
<string name="removePhoto" msgid="4898105274130284565">"Remover foto"</string>
<string name="noContacts" msgid="8579310973261953559">"Nenhum contato."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nenhum grupo."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nenhum contato correspondente foi encontrado."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nenhum contato com números de telefone."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Apenas contatos com telefones"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> encontrados"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contatos"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupos"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoritos"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefone"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Chamadas"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"O registro de chamadas está vazio."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Limpar registro de chamadas"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Tem certeza de que deseja limpar o registro de chamadas?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Limpando registro de chamadas"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Correio de voz"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nenhum cartão SD detectado"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Pesquisando vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importar do cartão SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importar do armazenamento"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportar para o armazenamento"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importar do armazenamento"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importar do cartão SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportar para o armazenamento"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportar para cartão SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Compartilhar contatos visíveis"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importar um arquivo do vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importar vários arquivos do vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Sobrenome fonético"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nome fonético"</string>
<string name="account_type_format" msgid="718948015590343010">"Contato de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Usar esta foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"As informações de contato de <xliff:g id="SOURCE">%1$s</xliff:g> não podem ser editadas neste aparelho."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Não há informações adicionais para este contato"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nenhum contato selecionado."</string>
<string name="add_field" msgid="2384260056674995230">"Adicionar outro campo"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Adicionar num. de tel."</string>
+ <string name="add_email" msgid="175079666329862215">"Adicionar novo e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Adic. conta de IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Adicionar endereço"</string>
+ <string name="add_note" msgid="2753771325725383279">"Adicionar nota"</string>
+ <string name="add_website" msgid="4312391288948517344">"Adicionar novo site"</string>
+ <string name="add_event" msgid="7488781591843886426">"Adicionar evento"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Adicionar relac."</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"por meio de <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorito"</string>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index f72d4ed..e558a89 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -101,6 +101,8 @@
<!-- no translation found for removePhoto (4898105274130284565) -->
<skip />
<string name="noContacts" msgid="8579310973261953559">"Nagins contacts"</string>
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
<string name="noMatchingContacts" msgid="4266283206853990471">"Betg chattà in contact correspundent."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nagin contact dispona d\'in numer da telefon."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Mo contacts cun telefon"</string>
@@ -138,6 +140,8 @@
<item quantity="other" msgid="7988132539476575389">"Chattà <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Contacts"</string>
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favurits"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Cloms"</string>
@@ -153,6 +157,8 @@
<string name="recentCalls_empty" msgid="247053222448663107">"La glista da cloms e vida"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Stizzar il protocol da cloms"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Vulais Vus propi stizzar il protocol da cloms?"</string>
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Mailbox"</string>
@@ -218,8 +224,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Betg chattà ina carta SD."</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Tschertgar datas vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importar da la carta SIM"</string>
- <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importar da la carta SD"</string>
- <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportar sin la carta SD"</string>
+ <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importar da la carta SD"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importar da la carta SD"</string>
+ <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportar sin la carta SD"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportar sin la carta SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Cundivider ils contacts visibels"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importar ina datoteca vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importar pliras datotecas vCard"</string>
@@ -426,7 +434,8 @@
<!-- no translation found for name_phonetic (4259595234312430484) -->
<skip />
<string name="account_type_format" msgid="718948015590343010">"Contact <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"da <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilisar quest foto"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Vus na pudais betg modifitgar las infurmaziuns dal contact <xliff:g id="SOURCE">%1$s</xliff:g> sin quest apparat."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Naginas infurmaziuns supplementaras per quest contact"</string>
@@ -467,6 +476,22 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Betg tschernì in contact"</string>
<!-- outdated translation 5257149039253569615 --> <string name="add_field" msgid="2384260056674995230">"Agiuntar infurmaziuns"</string>
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
<string name="contact_status_update_attribution" msgid="752179367353018597">"entras <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> entras <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favurit"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 59bc5e3..e42bca9 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Prestabilit"</string>
<string name="removePhoto" msgid="4898105274130284565">"Eliminaţi fotografia"</string>
<string name="noContacts" msgid="8579310973261953559">"Nicio persoană în agendă."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Nu există grupuri."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nu a fost găsită nicio persoană potrivită în agendă."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Nicio persoană din agendă cu numere de telefon."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Numai persoanele din agendă cu numere de telefon"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Au fost găsite <xliff:g id="COUNT">%d</xliff:g> (de) persoane din agendă"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Agendă"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupuri"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favorite"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Jurnal de apeluri"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Jurnalul de apeluri este gol."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Ştergeţi jurnalul de apeluri"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Sigur doriţi ştergerea jurnalului de apeluri?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Se goleşte jurnalul de apeluri"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Mesagerie vocală"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Niciun card SD detectat"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Se caută date în format vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importaţi de pe cardul SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importaţi din stocare"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportaţi în stocare"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importaţi din stocare"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importaţi de pe cardul SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportaţi în stocare"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportaţi pe cardul SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Distribuiţi persoanele vizibile din agendă"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importaţi un fişier vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importaţi fişiere multiple vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Numele de familie fonetic"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Nume fonetic"</string>
<string name="account_type_format" msgid="718948015590343010">"Persoana din agendă din <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"din <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Utilizaţi această fotografie"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> Informaţiile despre această persoană din agendă nu se pot edita pe acest dispozitiv."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Nicio informaţie suplimentară pentru această persoană din agendă"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nu aţi selectat nicio persoană din Agendă."</string>
<string name="add_field" msgid="2384260056674995230">"Adăugaţi alt câmp"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Adăugaţi nr. tel. nou"</string>
+ <string name="add_email" msgid="175079666329862215">"Adăugaţi e-mail nou"</string>
+ <string name="add_im" msgid="5158094627521120439">"Adăugaţi cont IM nou"</string>
+ <string name="add_address" msgid="418292312672970688">"Adăugaţi adresă nouă"</string>
+ <string name="add_note" msgid="2753771325725383279">"Adăugaţi notă nouă"</string>
+ <string name="add_website" msgid="4312391288948517344">"Adăugaţi site web nou"</string>
+ <string name="add_event" msgid="7488781591843886426">"Adăugaţi eveniment nou"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Adăugaţi relaţie nouă"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"de pe <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"La ora <xliff:g id="DATE">%1$s</xliff:g> de pe <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"preferate"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 9fdd22a..14960cc 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"По умолчанию"</string>
<string name="removePhoto" msgid="4898105274130284565">"Удалить фото"</string>
<string name="noContacts" msgid="8579310973261953559">"Нет контактов."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Нет групп."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Подходящие контакты не найдены."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Нет контактов с номерами телефонов."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Контакты с телефонами"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Найдено: <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Контакты"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Группы"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Избранное"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Кнопки"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Вызовы"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Список вызовов пуст."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Очистить список вызовов"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Действительно очистить список вызовов?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Очистка списка вызовов"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Голосовая почта"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"SD-карта не обнаружена"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Поиск vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Импортировать с SIM-карты"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Импорт из накопителя"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Экспорт на накопитель"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Импорт из накопителя"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Импортировать с SD-карты"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Экспорт на накопитель"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Экспортировать на SD-карту"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Передать видимые контакты"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Импорт одного файла VCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Импорт нескольких файлов vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Фамилия (транскрипция)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Транскрипция имени"</string>
<string name="account_type_format" msgid="718948015590343010">"Контакт <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"из <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Использовать эту фотографию"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Невозможно изменить контактную информацию <xliff:g id="SOURCE">%1$s</xliff:g> на этом устройстве."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Отсутствует дополнительная информация об этом контакте."</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Контакты не выбраны."</string>
<string name="add_field" msgid="2384260056674995230">"Добавить другое поле"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Добавить тел. номер"</string>
+ <string name="add_email" msgid="175079666329862215">"Добавить эл. почту"</string>
+ <string name="add_im" msgid="5158094627521120439">"Добавить чат"</string>
+ <string name="add_address" msgid="418292312672970688">"Добавить адрес"</string>
+ <string name="add_note" msgid="2753771325725383279">"Добавить примечание"</string>
+ <string name="add_website" msgid="4312391288948517344">"Добавить веб-сайт"</string>
+ <string name="add_event" msgid="7488781591843886426">"Добавить событие"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Добавить отношение"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"с помощью <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> с помощью <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"избранное"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index af8eb8e..9fa725f 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Predvolené"</string>
<string name="removePhoto" msgid="4898105274130284565">"Odstrániť fotografiu"</string>
<string name="noContacts" msgid="8579310973261953559">"Žiadne kontakty."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Žiadne skupiny."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Nenašli sa žiadne zodpovedajúce kontakty."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Ku kontaktom nie sú priradené žiadne telefónne čísla."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Iba kontakty s telefónmi"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Počet nájdených položiek: <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakty"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Skupiny"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Obľúbené"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefón"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Denník hovorov"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Záznam hovorov je prázdny."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Vymazať záznam hovorov"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Naozaj chcete odstrániť denník hovorov?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Vymazávanie denníka hovorov"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Hlasová schránka"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Nebola zistená žiadna karta SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Vyhľadávanie karty vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importovať z karty SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Import z ukl. priestoru"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Export do uklad. priest."</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Import z ukl. priestoru"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importovať z karty SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Export do uklad. priest."</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportovať na kartu SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Zdieľať viditeľné kontakty"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importovať jeden súbor vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importovať niekoľko súborov vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Priezvisko (foneticky)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Meno (foneticky)"</string>
<string name="account_type_format" msgid="718948015590343010">"Kontakt <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"z miesta: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Použiť túto fotografiu"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Kontaktné informácie zo zdroja <xliff:g id="SOURCE">%1$s</xliff:g> nie je možné na tomto zariadení upraviť."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Pri tomto kontakte nie sú uvedené ďalšie informácie"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Nie sú vybraté žiadne kontakty."</string>
<string name="add_field" msgid="2384260056674995230">"Pridať ďalšie pole"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Pridať nové tel. číslo"</string>
+ <string name="add_email" msgid="175079666329862215">"Pridať nový e-mail"</string>
+ <string name="add_im" msgid="5158094627521120439">"Pridať nový účet IM"</string>
+ <string name="add_address" msgid="418292312672970688">"Pridať novú adresu"</string>
+ <string name="add_note" msgid="2753771325725383279">"Pridať novú poznámku"</string>
+ <string name="add_website" msgid="4312391288948517344">"Pridať novú lokalitu"</string>
+ <string name="add_event" msgid="7488781591843886426">"Pridať novú udalosť"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Pridať nový vzťah"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">", zdroj: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g>, zdroj: <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"zaradiť medzi obľúbené"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 47e7a9b..2c93af8 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Privzeto"</string>
<string name="removePhoto" msgid="4898105274130284565">"Odstrani fotografijo"</string>
<string name="noContacts" msgid="8579310973261953559">"Ni stikov."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Ni skupin."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Najti ni bilo mogoče nobenega ustreznega stika."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Ni stikov s telefonskimi številkami."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Samo stiki s telefoni"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> najdenih"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Stiki"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Skupine"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Priljubljeno"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Dnevnik klicev"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Dnevnik klicev je prazen."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Počisti dnevnik klicev"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Ali ste prepričani, da želite počistiti dnevnik klicev?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Brisanje dnevnika klicev"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Glasovna pošta"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Kartica SD ni bila zaznana"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Iskanje vizitke vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Uvozi s kartice SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Uvoz iz pomnilnika"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Izvoz v pomnilnik"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Uvoz iz pomnilnika"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Uvozi s kartice SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Izvoz v pomnilnik"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Izvozi na kartico SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Vidne stike deli z drugimi"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Uvozi eno datoteko z vizitko vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Uvozi več datotek z vizitko vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Priimek – fonetično"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Ime – fonetično"</string>
<string name="account_type_format" msgid="718948015590343010">"Stik <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"od <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Uporabi to fotografijo"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Podatkov o stiku <xliff:g id="SOURCE">%1$s</xliff:g> s to napravo ni mogoče urejati."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Ni dodatnih informacij za ta stik"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Izbran ni noben stik."</string>
<string name="add_field" msgid="2384260056674995230">"Dodaj drugo polje"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Dodaj novo telefonsko številko"</string>
+ <string name="add_email" msgid="175079666329862215">"Dodaj novo e-pošto"</string>
+ <string name="add_im" msgid="5158094627521120439">"Dodaj nov račun za NS"</string>
+ <string name="add_address" msgid="418292312672970688">"Dodaj nov naslov"</string>
+ <string name="add_note" msgid="2753771325725383279">"Dodaj novo opombo"</string>
+ <string name="add_website" msgid="4312391288948517344">"Dodaj novo spletno mesto"</string>
+ <string name="add_event" msgid="7488781591843886426">"Dodaj nov dogodek"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Dodaj novo razmerje"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"prek <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> prek <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"priljubljeno"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 2af6d13..1615287 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Подразумевано"</string>
<string name="removePhoto" msgid="4898105274130284565">"Уклони фотографију"</string>
<string name="noContacts" msgid="8579310973261953559">"Нема контаката."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Нема група."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Није пронађен ниједан одговарајући контакт."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Нема контаката за које су унети бројеви телефона."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Само контакти за које су унети бројеви телефона"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> пронађено"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Контакти"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Групе"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Омиљено"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Телефон"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Евиденција позива"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Евиденција позива је празна."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Обриши евиденцију позива"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Желите ли заиста да обришете евиденцију позива?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Брисање евиденције позива"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Говорна пошта"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Није изабрана ниједна SD картица"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Претрага дигиталне визиткарте"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Увези са SIM картице"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Увези из меморије"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Извези у меморију"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Увези из меморије"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Увези са SD картице"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Извези у меморију"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Извези на SD картицу"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Дели видљиве контакте"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Увези једну датотеку дигиталне визиткарте"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Увези више датотека дигиталних визиткарата"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Презиме – фонетски"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Име – фонетски"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> контакт"</string>
- <string name="from_account_format" msgid="687567483928582084">"са <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Користи ову фотографију"</string>
<string name="contact_read_only" msgid="1203216914575723978">"На овом уређају није могуће изменити информације о контакту <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Нема додатних информације за овај контакт"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Није изабран ниједан контакт."</string>
<string name="add_field" msgid="2384260056674995230">"Додај друго поље"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Додајте нови телефон"</string>
+ <string name="add_email" msgid="175079666329862215">"Додајте нову адресу"</string>
+ <string name="add_im" msgid="5158094627521120439">"Додајте нови IM налoг"</string>
+ <string name="add_address" msgid="418292312672970688">"Додајте нову адресу"</string>
+ <string name="add_note" msgid="2753771325725383279">"Додајте нову белешку"</string>
+ <string name="add_website" msgid="4312391288948517344">"Додајте нови веб сајт"</string>
+ <string name="add_event" msgid="7488781591843886426">"Додајте нови догађај"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Додајте нову везу"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"преко <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> преко <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"омиљено"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index fe750e4..96cf1c2 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Standardinställning"</string>
<string name="removePhoto" msgid="4898105274130284565">"Ta bort foto"</string>
<string name="noContacts" msgid="8579310973261953559">"Inga kontakter."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Inga grupper."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Inga matchande kontakter hittades."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Inga kontakter med telefonnummer."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Bara kontakter med telefoner"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> hittades"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kontakter"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Grupper"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Favoriter"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Samtalshistorik"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Samtalshistoriken är tom."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Rensa samtalshistorik"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Vill du rensa samtalshistoriken?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Rensar samtalshistorik"</string>
<string name="imei" msgid="3045126336951684285">"IMEI-kod"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Röstbrevlåda"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Inget SD-kort hittades"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Söker efter vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Importera från SIM-kort"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Importera från lagring"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Exportera till lagring"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Importera från lagring"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Importera från SD-kort"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Exportera till lagring"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Exportera till SD-kort"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Dela synliga kontakter"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Importera en vCard-fil"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Importera flera vCard-filer"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetiskt efternamn"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetiskt namn"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g>-kontakt"</string>
- <string name="from_account_format" msgid="687567483928582084">"från <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Använd det här fotot"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Kontaktinformation för <xliff:g id="SOURCE">%1$s</xliff:g> kan inte redigeras i den här enheten."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Det finns ingen mer information för kontakten"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Inga kontakter har markerats."</string>
<string name="add_field" msgid="2384260056674995230">"Lägg till ett fält"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Lägg till nytt nummer"</string>
+ <string name="add_email" msgid="175079666329862215">"Lägg till ny e-post"</string>
+ <string name="add_im" msgid="5158094627521120439">"Lägg till IM-konto"</string>
+ <string name="add_address" msgid="418292312672970688">"Lägg till ny adress"</string>
+ <string name="add_note" msgid="2753771325725383279">"Lägg till kommentar"</string>
+ <string name="add_website" msgid="4312391288948517344">"Lägg till ny webbplats"</string>
+ <string name="add_event" msgid="7488781591843886426">"Lägg till ny aktivitet"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Lägg till ny relation"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"via <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> via <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favorit"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
new file mode 100644
index 0000000..a540ad8
--- /dev/null
+++ b/res/values-sw/strings.xml
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sharedUserLabel" msgid="7965035505237135241">"Programu Msingi za Android"</string>
+ <!-- no translation found for contactsList (8661624236494819731) -->
+ <skip />
+ <string name="launcherDialer" msgid="8636288196618486553">"Simu"</string>
+ <!-- no translation found for shortcutContact (749243779392912958) -->
+ <skip />
+ <string name="shortcutDialContact" msgid="746622101599186779">"Upigaji wa moja kwa moja"</string>
+ <string name="shortcutMessageContact" msgid="2460337253595976198">"Ujumbe wa moja kwa moja"</string>
+ <string name="shortcutActivityTitle" msgid="6642877210643565436">"Chagua njia ya mkato ya anwani"</string>
+ <string name="callShortcutActivityTitle" msgid="6065749861423648991">"Chagua nambari ya kupiga"</string>
+ <string name="messageShortcutActivityTitle" msgid="3084542316620335911">"Chagua nambari ya kutumia ujumbe"</string>
+ <!-- no translation found for contactPickerActivityTitle (6886592363525235031) -->
+ <skip />
+ <!-- no translation found for starredList (4817256136413959463) -->
+ <skip />
+ <!-- no translation found for frequentList (7154768136473953056) -->
+ <skip />
+ <!-- no translation found for strequentList (5640192862059373511) -->
+ <skip />
+ <!-- no translation found for viewContactTitle (7989394521836644384) -->
+ <skip />
+ <!-- no translation found for viewContactDesription (214186610887547860) -->
+ <skip />
+ <!-- no translation found for editContactDescription (2947202828256214947) -->
+ <skip />
+ <!-- no translation found for insertContactDescription (4709878105452681987) -->
+ <skip />
+ <!-- no translation found for searchHint (8482945356247760701) -->
+ <skip />
+ <string name="menu_search" msgid="9147752853603483719">"Tafuta"</string>
+ <!-- no translation found for menu_newContact (1209922412763274638) -->
+ <skip />
+ <!-- no translation found for menu_viewContact (2795575601596468581) -->
+ <skip />
+ <string name="menu_callNumber" msgid="5142851348489387516">"Piga simu <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for menu_addStar (2908478235715404876) -->
+ <skip />
+ <!-- no translation found for menu_removeStar (5844227078364227030) -->
+ <skip />
+ <!-- no translation found for menu_editContact (3452858480713561396) -->
+ <skip />
+ <!-- no translation found for menu_deleteContact (1916555454274101750) -->
+ <skip />
+ <string name="menu_call" msgid="3992595586042260618">"Mpigie"</string>
+ <string name="menu_sendSMS" msgid="5535886767547006515">"Tuma ujumbe kwa anwani"</string>
+ <string name="menu_makeDefaultEmail" msgid="2599044610375789994">"Fanya iwe barua pepe chaguo-msingi"</string>
+ <string name="menu_splitAggregate" msgid="8368636463748691868">"Kando"</string>
+ <!-- no translation found for menu_renameGroup (2798886925154156075) -->
+ <skip />
+ <!-- no translation found for menu_deleteGroup (644571524292675446) -->
+ <skip />
+ <!-- no translation found for menu_new_contact_action_bar (8887818026717394343) -->
+ <skip />
+ <string name="splitConfirmation_title" msgid="6716467920283502570">"Tenganisha Anwani"</string>
+ <string name="splitConfirmation" msgid="1150797297503944823">"Je, una uhakika kuwa unataka kutenganisha anwani hii moja kwa anwani nyingi: moja kwa kila seti ya maelezo ya anwani ambayo yaliunganishwa kwake?"</string>
+ <string name="menu_joinAggregate" msgid="5027981918265667970">"Jiunge"</string>
+ <string name="titleJoinContactDataWith" msgid="7684875775798635354">"Unganisha anwani"</string>
+ <string name="blurbJoinContactDataWith" msgid="995870557595050304">"Chagua anwani unayotaka kujiunga nayo <xliff:g id="NAME">%s</xliff:g>."</string>
+ <string name="showAllContactsJoinItem" msgid="2189695051430392383">"Onyesha anwani zote"</string>
+ <string name="separatorJoinAggregateSuggestions" msgid="2831414448851313345">"Anwani zilizopendekezwa"</string>
+ <string name="separatorJoinAggregateAll" msgid="7939932265026181043">"Anwani zote"</string>
+ <string name="contactsJoinedMessage" msgid="7208148163607047389">"Anwani zimeunganishwa"</string>
+ <string name="menu_contactOptions" msgid="1957061455705020617">"Chaguo"</string>
+ <string name="contactOptionsTitle" msgid="8259347644090700915">"Chaguo"</string>
+ <!-- no translation found for deleteConfirmation_title (6394309508930335204) -->
+ <skip />
+ <string name="readOnlyContactWarning" msgid="1390849295342594265">"Huwezi kufuta anwani kutoka kwa akaunti zinazoweza kusomwa tu, lakini unaweza kuzificha katika orodha yako ya anwani."</string>
+ <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"Anwani hii ina maelezo kutoka kwa akaunti nyingi. Maelezo kutoka kwa akaunti za soma-tu zitafichwa katika orodha zako za anwani, sio kufutwa."</string>
+ <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"Kufuta anwani hii kutafuta maelezo kutoka kwa akaunti nyingi."</string>
+ <!-- no translation found for deleteConfirmation (811706994761610640) -->
+ <skip />
+ <string name="menu_done" msgid="796017761764190697">"Kwisha"</string>
+ <!-- outdated translation 2174577548513895144 --> <string name="menu_doNotSave" msgid="58593876893538465">"Rudi"</string>
+ <!-- no translation found for editContact_title_edit (7678695190666836093) -->
+ <skip />
+ <!-- no translation found for editContact_title_insert (9125600232291405757) -->
+ <skip />
+ <string name="label_phonetic_name" msgid="2288082649573927286">"Fonetiki"</string>
+ <!-- no translation found for label_notes (8337354953278341042) -->
+ <skip />
+ <string name="label_sip_address" msgid="124073911714324974">"Simu ya wavuti"</string>
+ <!-- no translation found for label_ringtone (8833166825330686244) -->
+ <skip />
+ <string name="ghostData_phonetic_name" msgid="7852749081984070902">"Jina la kifonetiki"</string>
+ <!-- no translation found for ghostData_company (5414421120553765775) -->
+ <skip />
+ <string name="ghostData_title" msgid="7496735200318496110">"Jina la heshima"</string>
+ <!-- no translation found for invalidContactMessage (5816991830260044593) -->
+ <skip />
+ <!-- no translation found for pickerNewContactHeader (7750705279843568147) -->
+ <skip />
+ <!-- no translation found for phoneLabelsGroup (6468091477851199285) -->
+ <skip />
+ <!-- no translation found for emailLabelsGroup (8389931313045344406) -->
+ <skip />
+ <!-- no translation found for imLabelsGroup (3898238486262614027) -->
+ <skip />
+ <!-- no translation found for postalLabelsGroup (3487738141112589324) -->
+ <skip />
+ <string-array name="otherLabels">
+ <item msgid="8287841928119937597">"Shirika"</item>
+ <item msgid="7196592230748086755">"Hati"</item>
+ </string-array>
+ <!-- no translation found for photoPickerNotFoundText (6247290728908599701) -->
+ <skip />
+ <!-- no translation found for photoPickerNotFoundText (431331662154342581) -->
+ <skip />
+ <!-- no translation found for attach_photo_dialog_title (5599827035558557169) -->
+ <skip />
+ <string name="customLabelPickerTitle" msgid="1081475101983255212">"Jina maalum la lebo"</string>
+ <string name="menu_displayGroup" msgid="5655505437727616553">"Chaguo za onyesho"</string>
+ <string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"Tuma simu moja kwa moja kwa barua ya sauti"</string>
+ <!-- no translation found for default_ringtone (9099988849649827972) -->
+ <skip />
+ <!-- no translation found for removePhoto (4898105274130284565) -->
+ <skip />
+ <!-- no translation found for noContacts (8579310973261953559) -->
+ <skip />
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
+ <string name="noMatchingContacts" msgid="4266283206853990471">"Hakuna anwani zinazolingana zilizopatikana."</string>
+ <!-- no translation found for noContactsWithPhoneNumbers (1605457050218824269) -->
+ <skip />
+ <string name="showFilterPhones" msgid="4184858075465653970">"Anwani zenye simu tu"</string>
+ <string name="showFilterPhonesDescrip" msgid="6644443248815191067">"Onyesha tu anwani ambazo zina nambari za simu"</string>
+ <string name="headerContactGroups" msgid="2426134991932503843">"Chagua anwani ili kuonyesha"</string>
+ <plurals name="groupDescrip">
+ <item quantity="other" msgid="3507881585720628389">"anwani <xliff:g id="COUNT">%0$d</xliff:g>"</item>
+ </plurals>
+ <plurals name="groupDescripPhones">
+ <item quantity="other" msgid="3816047547470490208">"Anwani <xliff:g id="COUNT_0">%1$d</xliff:g>, <xliff:g id="COUNTWITHPHONES">%2$d</xliff:g> zenye simu"</item>
+ </plurals>
+ <string name="savingContact" msgid="4075751076741924939">"Inahifadhi anwani..."</string>
+ <string name="savingDisplayGroups" msgid="2133152192716475939">"Inahifadhi chaguo za mwonyesho.."</string>
+ <!-- no translation found for contactSavedToast (7152589189385441091) -->
+ <skip />
+ <string name="contactSavedErrorToast" msgid="9189098776225004666">"Hitilafu, haiwezi kuhifadhi mabadiliko ya anwani."</string>
+ <plurals name="listTotalPhoneContacts">
+ <item quantity="one" msgid="3015357862286673986">"Anwani 1 yenye namba ya simu"</item>
+ <item quantity="other" msgid="3299954047880968205">"Anwani <xliff:g id="COUNT">%d</xliff:g> zilizo na nambari ya simu"</item>
+ </plurals>
+ <!-- outdated translation 2756295259674938869 --> <string name="listTotalPhoneContactsZero" msgid="6968813857632984319">"Hakuna anwani zinazoonekana zenye nambari za simu"</string>
+ <plurals name="listTotalAllContacts">
+ <item quantity="one" msgid="3405747744700823280">"Anwani 1"</item>
+ <item quantity="other" msgid="3578469907265375314">"Anwani <xliff:g id="COUNT">%d</xliff:g>"</item>
+ </plurals>
+ <!-- outdated translation 6811347506748072822 --> <string name="listTotalAllContactsZero" msgid="1889349925514589304">"Hakuna anwani zinazoonekana"</string>
+ <!-- no translation found for listTotalAllContactsZeroCustom (4058252141420128998) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroStarred (5391630590684099117) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroGroup (5448979458248027615) -->
+ <skip />
+ <plurals name="listFoundAllContacts">
+ <item quantity="one" msgid="5517063038754171134">"Imepatikana 1"</item>
+ <item quantity="other" msgid="3852668542926965042">"Patikana <xliff:g id="COUNT">%d</xliff:g>"</item>
+ </plurals>
+ <string name="foundTooManyContacts" msgid="2548148047461758967">"zaidi ya <xliff:g id="COUNT">%d</xliff:g> yamepatikana"</string>
+ <string name="listFoundAllContactsZero" msgid="777952841930508289">"Haikupatikana"</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one" msgid="4826918429708286628">"Patikana 1"</item>
+ <item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> zimepatikana"</item>
+ </plurals>
+ <!-- no translation found for contactsIconLabel (7666609097606552806) -->
+ <skip />
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
+ <!-- no translation found for contactsFavoritesLabel (8417039765586853670) -->
+ <skip />
+ <string name="dialerIconLabel" msgid="6500826552823403796">"Simu"</string>
+ <!-- no translation found for recentCallsIconLabel (1419116422359067949) -->
+ <skip />
+ <string name="liveFolderAll" msgid="4789010460767506206">"Anwani zote"</string>
+ <string name="liveFolderFavorites" msgid="3100957542927222282">"Anwani zenye nyota"</string>
+ <string name="liveFolderPhone" msgid="3739376066610926780">"Anwani zenye nambari za simu"</string>
+ <string name="menu_sendTextMessage" msgid="6937343460284499306">"Tuma ujumbe wa maandishi"</string>
+ <string name="recentCalls_callNumber" msgid="1756372533999226126">"Pigia <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for recentCalls_editNumberBeforeCall (7756171675833267857) -->
+ <skip />
+ <!-- no translation found for recentCalls_addToContact (1429899535546487008) -->
+ <skip />
+ <!-- no translation found for recentCalls_removeFromRecentList (401662244636511330) -->
+ <skip />
+ <!-- no translation found for recentCalls_deleteAll (6352364392762163704) -->
+ <skip />
+ <!-- no translation found for recentCalls_empty (247053222448663107) -->
+ <skip />
+ <string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Futa kumbukumbu la upigaji simu"</string>
+ <string name="clearCallLogConfirmation" msgid="7625927669136267636">"Je, una uhakika kuwa unataka kufuta kumbukumbu ya upigaji simu?"</string>
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
+ <!-- no translation found for imei (3045126336951684285) -->
+ <skip />
+ <string name="meid" msgid="6210568493746275750">"MEID"</string>
+ <!-- no translation found for voicemail (3851469869202611441) -->
+ <skip />
+ <!-- no translation found for unknown (740067747858270469) -->
+ <skip />
+ <!-- no translation found for private_num (6374339738119166953) -->
+ <skip />
+ <string name="payphone" msgid="4864313342828942922">"Simu ya kulipia"</string>
+ <!-- no translation found for dialerKeyboardHintText (5401660096579787344) -->
+ <skip />
+ <string name="dialerDialpadHintText" msgid="5824490365898349041">"Piga ili kuongeza simu"</string>
+ <!-- no translation found for simContacts_emptyLoading (6700035985448642408) -->
+ <skip />
+ <!-- no translation found for simContacts_title (27341688347689769) -->
+ <skip />
+ <string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"Huna anwani zozote ya kuonyesha. (Ikiwa umeongeza tu akaunti, inaweza kuchukua dakika chache ili kusawazisha anwani.)"</string>
+ <string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">"Hauna anwani zozote za kuonyesha."</string>
+ <!-- outdated translation 7633826236417884130 --> <string name="noContactsHelpText" product="tablet" msgid="6450346791169710787">"Huna anwani zozote za kuonyesha."\n\n"Ili kuongeza anwani, bonyeza menyu ya "<font fgcolor="#ffffffff"><b></b></font>" kisha gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kuweka akaunti iliyo na anwani unazoweza kusawazisha kwenye simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" Ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>" Ili kuleta anwani kutoka kwenye kadi yako ya SIM au SD"\n</li></string>
+ <string name="noContactsHelpText" product="default" msgid="7633826236417884130">"Huna anwani zozote za kuonyesha."\n\n"Ili kuongeza anwani, bonyeza menyu ya "<font fgcolor="#ffffffff"><b></b></font>" kisha gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kuweka akaunti iliyo na anwani unazoweza kusawazisha kwenye simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" Ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>" Ili kuleta anwani kutoka kwenye kadi yako ya SIM au SD"\n</li></string>
+ <!-- outdated translation 3017521127042216243 --> <string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"Huna anwani zozote za kuonyesha. (Ikiwa uliongeza akaunti tu, haiwezi kuchukuwa dakika chache ili kusawazisha anwani.)"\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" kisha gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi akaunti kwa anwani unaweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Onyesha chaguo"</b></font>" ili kubadilisha anwani zinazoonekana"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwenye kadi yako ya SIm au SD"\n</li></string>
+ <string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"Huna anwani zozote za kuonyesha. (Ikiwa uliongeza akaunti tu, haiwezi kuchukuwa dakika chache ili kusawazisha anwani.)"\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" kisha gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi akaunti kwa anwani unaweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Onyesha chaguo"</b></font>" ili kubadilisha anwani zinazoonekana"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwenye kadi yako ya SIm au SD"\n</li></string>
+ <!-- outdated translation 467658807711582876 --> <string name="noContactsNoSimHelpText" product="tablet" msgid="6031363021287849874">"Huna anwani zozote za kuonyesha."\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" na gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi akaunti ya anwani unaweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Mawasiliano mapya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"</li>" "\n\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwa kadi yako ya SD"\n</li></string>
+ <string name="noContactsNoSimHelpText" product="default" msgid="467658807711582876">"Huna anwani zozote za kuonyesha."\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" na gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi akaunti ya anwani unaweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Mawasiliano mapya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"</li>" "\n\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwa kadi yako ya SD"\n</li></string>
+ <!-- outdated translation 9040060730467973050 --> <string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"Hauna anwani zozote za kuonyesha. (Kama umeongeza tu akaunti, inaweza kuchukua dadika chache ili kupatanisha anwani.)"\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" na gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi anwani unayoweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Onyesha Machaguo"</b></font>"ili kubadilisha anwani zinazoonekana"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwa kadi yako ya SD"\n</li></string>
+ <string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"Hauna anwani zozote za kuonyesha. (Kama umeongeza tu akaunti, inaweza kuchukua dadika chache ili kupatanisha anwani.)"\n\n"Ili kuongeza anwani, bonyeza "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" na gusa:"\n" "\n<li><font fgcolor="#ffffffff"><b>"Akaunti"</b></font>" ili kuongeza au kusanidi anwani unayoweza kupatanisha katika simu"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Onyesha Machaguo"</b></font>"ili kubadilisha anwani zinazoonekana"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Anwani mpya"</b></font>" ili kuunda anwani mpya kuanzia mwanzo"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Leta/Hamisha"</b></font>"ili kuleta anwani kutoka kwa kadi yako ya SD"\n</li></string>
+ <!-- syntax error in translation for noFavoritesHelpText (3744655776704833277) org.xmlpull.v1.XmlPullParserException: expected: /string read: b (position:END_TAG </b>@1:167 in java.io.StringReader@37d2068d) -->
+ <string name="liveFolder_all_label" msgid="5961411940473276616">"Anwani zote"</string>
+ <string name="liveFolder_favorites_label" msgid="2674341514070517105">"Yenye nyota"</string>
+ <string name="liveFolder_phones_label" msgid="1709786878793436245">"Simu"</string>
+ <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Tumia kibao cha kuchapa cha sauti na kugusa"</string>
+ <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Rudi kwa simu inayoendelea"</string>
+ <string name="dialer_addAnotherCall" msgid="4205688819890074468">"Ongeza simu"</string>
+ <string name="callDetailTitle" msgid="5340227785196217938">"Maelezo ya simu"</string>
+ <string name="toast_call_detail_error" msgid="7200975244804730096">"Haikuweza kusoma maelezo ya simu iliyoombwa."</string>
+ <string name="type_incoming" msgid="6502076603836088532">"Simu inayoingia"</string>
+ <string name="type_outgoing" msgid="343108709599392641">"Simu inayotoka"</string>
+ <string name="type_missed" msgid="2720502601640509542">"Simu isiyojibiwa"</string>
+ <string name="actionIncomingCall" msgid="6028930669817038600">"Simu zinazoingia"</string>
+ <string name="callBack" msgid="5498224409038809224">"Mpigie"</string>
+ <string name="callAgain" msgid="3197312117049874778">"Piga simu tena"</string>
+ <string name="returnCall" msgid="8171961914203617813">"Mpigie"</string>
+ <string name="callDetailsDurationFormat" msgid="8157706382818184268">"Dakika <xliff:g id="MINUTES">%s</xliff:g> sekunde <xliff:g id="SECONDS">%s</xliff:g>"</string>
+ <string name="favoritesFrquentSeparator" msgid="8107518433381283736">" Unaowasiliana nao zaidi"</string>
+ <string name="add_contact_dlg_title" msgid="2896685845822146494">"Ongeza anwani"</string>
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Ongeza \"<xliff:g id="EMAIL">%s</xliff:g>\" kwa anwani?"</string>
+ <string name="description_image_button_one" msgid="1740638037139856139">"moja"</string>
+ <string name="description_image_button_two" msgid="5882638439003731308">"mbili"</string>
+ <string name="description_image_button_three" msgid="8709731759376015180">"tatu"</string>
+ <string name="description_image_button_four" msgid="3530239685642246130">"nne"</string>
+ <string name="description_image_button_five" msgid="1182465427501188413">"tano"</string>
+ <string name="description_image_button_six" msgid="2093656269261415475">"sita"</string>
+ <string name="description_image_button_seven" msgid="2450357020447676481">"saba"</string>
+ <string name="description_image_button_eight" msgid="6969435115163287801">"nane"</string>
+ <string name="description_image_button_nine" msgid="7857248695662558323">"tisa"</string>
+ <string name="description_image_button_star" msgid="3365919907520767866">"nyota"</string>
+ <string name="description_image_button_zero" msgid="4133108949401820710">"sufuri"</string>
+ <string name="description_image_button_pound" msgid="3039765597595889230">"Pauni"</string>
+ <string name="description_voicemail_button" msgid="3402506823655455591">"Barua ya sauti"</string>
+ <string name="description_dial_button" msgid="1274091017188142646">"piga simu"</string>
+ <string name="description_delete_button" msgid="6263102114033407382">"futa"</string>
+ <string name="description_digits_edittext" msgid="8760207516497016437">"nambari ya kupiga"</string>
+ <string name="description_contact_photo" msgid="3387458082667894062">"picha ya anwani"</string>
+ <string name="description_minus_button" msgid="387136707700230172">"kutoa"</string>
+ <string name="description_plus_button" msgid="515164827856229880">"jumlisha"</string>
+ <!-- outdated translation 5911758680339949273 --> <string name="no_sdcard_title" product="nosdcard" msgid="8543619259870877473">"Hakuna kadi ya SD"</string>
+ <string name="no_sdcard_title" product="default" msgid="5911758680339949273">"Hakuna kadi ya SD"</string>
+ <!-- outdated translation 6019391476490445358 --> <string name="no_sdcard_message" product="nosdcard" msgid="1334170151822669976">"Hakuna kadi ya SD iliyogunduliwa"</string>
+ <string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Hakuna kadi ya SD iliyogunduliwa"</string>
+ <string name="searching_vcard_title" msgid="4970508055399376813">"Inatafuta vCard"</string>
+ <string name="import_from_sim" msgid="3859272228033941659">"Ingiza kutoka kwa SIM kadi"</string>
+ <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Ingiza kutoka kwa kadi ya SD"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Ingiza kutoka kwa kadi ya SD"</string>
+ <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Hamisha kwa kadi ya SD"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Hamisha kwa kadi ya SD"</string>
+ <string name="share_visible_contacts" msgid="890150378880783797">"Shiriki anwani zinazoonekana"</string>
+ <string name="import_one_vcard_string" msgid="9059163467020328433">"Ingiza faili moja ya vKadi"</string>
+ <string name="import_multiple_vcard_string" msgid="3810226492811062392">"Ingiza faili anuwai za vCard"</string>
+ <string name="import_all_vcard_string" msgid="5518136113853448474">"Ingiza faili zote za vKadi"</string>
+ <!-- outdated translation 6917522333561434546 --> <string name="searching_vcard_message" product="nosdcard" msgid="996170203695743981">"Inatafuta data ya vKadi kwenye kadi ya SD"</string>
+ <string name="searching_vcard_message" product="default" msgid="6917522333561434546">"Inatafuta data ya vKadi kwenye kadi ya SD"</string>
+ <!-- outdated translation 3506782007953167180 --> <string name="scanning_sdcard_failed_title" product="nosdcard" msgid="6957414493948497249">"Imeshindwa kuchunguza kadi ya SD"</string>
+ <string name="scanning_sdcard_failed_title" product="default" msgid="3506782007953167180">"Imeshindwa kuchunguza kadi ya SD"</string>
+ <!-- no translation found for scanning_sdcard_failed_message (4106156155205860626) -->
+ <skip />
+ <string name="scanning_sdcard_failed_message" product="default" msgid="3761992500690182922">"Imeshindwa kuchunguza kadi ya SD (Sababu: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\")"</string>
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"Hitilafu ya I/O"</string>
+ <string name="fail_reason_low_memory_during_import" msgid="7514918659342886381">"Kumbukumbu haitoshi (faili inaweza kuwa kubwa zaidi)"</string>
+ <string name="fail_reason_vcard_parse_error" msgid="1201233722762680214">"Imeshindwa kuchanganua vCard kwa sababu zisizotarajiwa"</string>
+ <!-- no translation found for fail_reason_not_supported (294499264620201243) -->
+ <skip />
+ <!-- no translation found for vcard_import_failed (7718330063493653085) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (6339234836196984924) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (1730986357514922756) -->
+ <skip />
+ <string name="fail_reason_failed_to_collect_vcard_meta_info" msgid="4154492282316067754">"Imeshindwa kukusanya habari ya faili ya vCard iliyotolewa."</string>
+ <string name="fail_reason_failed_to_read_files" msgid="3659521123567134029">"Faili moja au zaidi zilishindwa kuingizwa (%s)."</string>
+ <string name="fail_reason_unknown" msgid="999034019513096768">"Hitilafu isiyojulikana"</string>
+ <string name="select_vcard_title" msgid="3968948173786172468">"Chagua faili ya vCard"</string>
+ <string name="caching_vcard_title" msgid="5009556022082659780">"Akibisha vCard(s) kwa uhifadhi wa muda wa karibu"</string>
+ <string name="caching_vcard_message" msgid="2380844718093378900">"Kifaa cha kuingiza kinaakibisha kadi ya/za vCard kwa hifadhi ya muda. Uingizaji asili utaanza baada ya muda mfupi."</string>
+ <string name="progress_notifier_message" msgid="2311011466908220528">"Inaingiza <xliff:g id="CURRENT_NUMBER">%s</xliff:g>/<xliff:g id="TOTAL_NUMBER">%s</xliff:g>: <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="importing_vcard_description" msgid="4245275224298571351">"Inaingiza <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="reading_vcard_failed_title" msgid="2162610359561887043">"Imeshindwa Kusoma data ya vCard"</string>
+ <string name="reading_vcard_canceled_title" msgid="1770608329958463131">"Usomaji wa data ya vCard ulibatilishwa"</string>
+ <!-- no translation found for importing_vcard_finished_title (3341541727268747967) -->
+ <skip />
+ <!-- no translation found for importing_vcard_canceled_title (6367906965439777280) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message (2804911199145873396) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message_with_default_name (1022969530654129470) -->
+ <skip />
+ <!-- no translation found for vcard_import_request_rejected_message (2592424820635325951) -->
+ <skip />
+ <!-- no translation found for vcard_export_will_start_message (2210241345252081463) -->
+ <skip />
+ <!-- no translation found for vcard_export_request_rejected_message (8259494002258326330) -->
+ <skip />
+ <!-- no translation found for vcard_unknown_filename (7171709890959915954) -->
+ <skip />
+ <string name="percentage" msgid="34897865327092209">"%s%%"</string>
+ <string name="confirm_export_title" msgid="7648747763127442983">"Thibitisha hamisho"</string>
+ <string name="confirm_export_message" msgid="3875683519257829750">"Una uhakika unataka kuhamisha orodha yako ya anwani hadi kwa \"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\""</string>
+ <string name="exporting_contact_failed_title" msgid="585823094820602526">"Imeshindwa kuhamisha data ya anwani"</string>
+ <string name="exporting_contact_failed_message" msgid="4151348002470298092">"Imeshindwa kuhamisha data ya anwani."\n"Sababu ya kushindwa: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_no_exportable_contact" msgid="4919714086648344495">"Hakuna anwani inayoweza kuhamishwa"</string>
+ <!-- outdated translation 7084146295639672658 --> <string name="fail_reason_too_many_vcard" product="nosdcard" msgid="3745507837635270265">"Kuna faili nyingi sana za vCard kwenye kadi ya SD"</string>
+ <string name="fail_reason_too_many_vcard" product="default" msgid="7084146295639672658">"Kuna faili nyingi sana za vCard kwenye kadi ya SD"</string>
+ <string name="fail_reason_too_long_filename" msgid="1915716071321839166">"Jina la faili linalohitajika ni refu sana (\"<xliff:g id="FILENAME">%s</xliff:g>\")"</string>
+ <!-- no translation found for exporting_vcard_finished_title (4259736138838583213) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_canceled_title (1827672399438062140) -->
+ <skip />
+ <string name="exporting_contact_list_title" msgid="9072240631534457415">"Inahamisha data ya anwani"</string>
+ <string name="exporting_contact_list_message" msgid="5640326540405486055">"Inahamisha data ya anwani kwa \"<xliff:g id="FILE_NAME">%s</xliff:g>\""</string>
+ <string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">"Haikuweza kuanzisha kihamishaji: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"Kosa limetokea wakati wa hali: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="composer_failed_to_get_database_infomation" msgid="3723109558155169053">"Imeshindwa kupata maelezo ya hifadhidata"</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="tablet" msgid="5161491059051198932">"Hakuna anwani inayoweza kuhamishwa. Ikiwa kwa uhakika unayo anwani kwenye simu yako, anwani zote huenda yakasimamishwa kutoka kwa kuhamishwa katika nje ya simu na watoaji huduma wa data."</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="default" msgid="322344221706924358">"Hakuna anwani inayoweza kuhamishwa. Ikiwa kwa uhakika unayo anwani kwenye simu yako, anwani zote huenda yakasimamishwa kutoka kwa kuhamishwa katika nje ya simu na watoaji huduma wa data."</string>
+ <string name="composer_not_initialized" msgid="8041534450748388843">"Kitungaji vKadi hakijaanzishwa vizuri"</string>
+ <string name="fail_reason_could_not_open_file" msgid="4013520943128739511">"Haikuweza kufungua \"<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> ya anwani <xliff:g id="TOTAL_NUMBER">%s</xliff:g>"</string>
+ <!-- no translation found for cancel_import_confirmation_title (5578683596010294836) -->
+ <skip />
+ <!-- no translation found for cancel_import_confirmation_message (8560937090143057107) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_title (6516467140276768528) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_message (1392976902396351957) -->
+ <skip />
+ <!-- no translation found for cancel_vcard_import_or_export_failed (7096533244663846810) -->
+ <skip />
+ <string name="search_settings_description" msgid="2675223022992445813">"Majina ya anwani zako"</string>
+ <string name="add_2sec_pause" msgid="9214012315201040129">"Ongeza usitishaji wa sekunde 2"</string>
+ <string name="add_wait" msgid="3360818652790319634">"Ongeza kusubiri"</string>
+ <string name="call_disambig_title" msgid="1911302597959335178">"Piga simu kwa kutumia"</string>
+ <string name="sms_disambig_title" msgid="4675399294513152364">"Tuma ujumbe kwa kutumia"</string>
+ <string name="make_primary" msgid="5829291915305113983">"Kumbuka chaguo hili"</string>
+ <string name="quickcontact_missing_app" msgid="4600366393134289038">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
+ <string name="quickcontact_remember_choice" msgid="5964536411579749424">"Kumbuka chaguo hili"</string>
+ <string name="quickcontact_missing_name" msgid="5590266114306996632">"Haijulikani"</string>
+ <string name="quickcontact_no_data" msgid="2098000859125253675">"Hakuna data"</string>
+ <!-- no translation found for quickcontact_clear_defaults_description (3792792870662989100) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_caption (4287306111861545753) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_button (8728754360205289059) -->
+ <skip />
+ <string name="menu_accounts" msgid="8499114602017077970">"Akaunti"</string>
+ <string name="menu_import_export" msgid="3765725645491577190">"Ingiza/Hamisha"</string>
+ <string name="dialog_import_export" msgid="4771877268244096596">"Ingiza/Hamisha anwani"</string>
+ <!-- outdated translation 943789700636542260 --> <string name="menu_share" msgid="8746849630474240344">"Shiriki"</string>
+ <string name="share_via" msgid="563121028023030093">"Shiriki anwani kupitia"</string>
+ <string name="share_error" msgid="4374508848981697170">"Anwani hii haiwezi kushirikiwa."</string>
+ <string name="nameLabelsGroup" msgid="2034640839640477827">"Jina"</string>
+ <string name="nicknameLabelsGroup" msgid="2891682101053358010">"Jina la utani"</string>
+ <string name="organizationLabelsGroup" msgid="2478611760751832035">"Shirika"</string>
+ <string name="websiteLabelsGroup" msgid="4202998982804009261">"Tovuti"</string>
+ <string name="eventLabelsGroup" msgid="8069912895912714412">"Tukio"</string>
+ <!-- no translation found for relationLabelsGroup (1854373894284572781) -->
+ <skip />
+ <string name="groupsLabel" msgid="8573535366319059326">"Vikundi"</string>
+ <string name="type_short_home" msgid="7770424864090605384">"H"</string>
+ <string name="type_short_mobile" msgid="1655473281466676216">"M"</string>
+ <string name="type_short_work" msgid="4925330752504537861">"W"</string>
+ <string name="type_short_pager" msgid="2613818970827594238">"P"</string>
+ <string name="type_short_other" msgid="5669407180177236769">"O"</string>
+ <string name="dialog_new_contact_account" msgid="9044704073286262197">"Unda anwani chini ya akaunti"</string>
+ <string name="menu_sync_remove" msgid="3266725887008450161">"Ondoa kikundi cha usawazishaji"</string>
+ <string name="dialog_sync_add" msgid="8267045393119375803">"Ongeza kikundi cha usawazishaji"</string>
+ <string name="display_more_groups" msgid="2682547080423434170">"Vikundi zaidi..."</string>
+ <string name="display_ungrouped" msgid="4602580795576261158">"Anwani Zingine Zote"</string>
+ <string name="display_all_contacts" msgid="6846131371214707956">"Anwani zote"</string>
+ <string name="display_warn_remove_ungrouped" msgid="2314043155909167610">"Kuondoa \'<xliff:g id="GROUP">%s</xliff:g>\' kutoka kwa usawazishaji kutaondoa pia anwani zozote zisizo katika kikundi kutoka kwa usawazishaji."</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="tablet" msgid="7946049152658522054">"Simu-tu (isiyosawazishwa)"</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="default" msgid="3682950835276226870">"Simu-tu (isiyosawazishwa)"</string>
+ <string name="call_custom" msgid="7756571794763171802">"Mpigie <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="call_home" msgid="1990519474420545392">"Piga simu nyumbani"</string>
+ <string name="call_mobile" msgid="7502236805487609178">"Pigia simu ya mkononi"</string>
+ <string name="call_work" msgid="5328785911463744028">"Piga simu kazini"</string>
+ <string name="call_fax_work" msgid="7467763592359059243">"Piga simu kwa pepesi ya kazini"</string>
+ <string name="call_fax_home" msgid="8342175628887571876">"Piga simu kwa pepesi ya nyumbani"</string>
+ <string name="call_pager" msgid="9003902812293983281">"Piga simu kwa peja"</string>
+ <string name="call_other" msgid="8563753966926932052">"Piga simu"</string>
+ <string name="call_callback" msgid="1910165691349426858">"Mpigie"</string>
+ <string name="call_car" msgid="3280537320306436445">"Piga simu kwa gari"</string>
+ <string name="call_company_main" msgid="6105120947138711257">"Pigia nambari kuu ya simu ya kampuni"</string>
+ <string name="call_isdn" msgid="1541590690193403411">"Piga simu kwa ISDN"</string>
+ <string name="call_main" msgid="6082900571803441339">"Piga simu kuu"</string>
+ <string name="call_other_fax" msgid="5745314124619636674">"Piga simu ya faksi"</string>
+ <string name="call_radio" msgid="8296755876398357063">"Piga simu kwa redio"</string>
+ <string name="call_telex" msgid="2223170774548648114">"Piga simu kwa telex"</string>
+ <string name="call_tty_tdd" msgid="8951266948204379604">"Pigia TTY/TDD"</string>
+ <string name="call_work_mobile" msgid="8707874281430105394">"Piga simu kwa simu ya mkononi ya kazini"</string>
+ <string name="call_work_pager" msgid="3419348514157949008">"Piga simu kwa peja"</string>
+ <string name="call_assistant" msgid="2141641383068514308">"Piga simu <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="call_mms" msgid="6274041545876221437">"Piga simu kwa MMS"</string>
+ <string name="sms_custom" msgid="5932736853732191825">"Tuma ujumbe kwa <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="sms_home" msgid="7524332261493162995">"Tuma ujumbe kwa simu ya nyumbani"</string>
+ <string name="sms_mobile" msgid="5200107250451030769">"Tuma ujumbe wa maandishi kwa simu ya mkononi"</string>
+ <string name="sms_work" msgid="2269624156655267740">"Tuma ujumbe kazini"</string>
+ <string name="sms_fax_work" msgid="8028189067816907075">"Tuma maandishi kwa faksi ya kazini"</string>
+ <string name="sms_fax_home" msgid="9204042076306809634">"Tuma ujumbe kwa pepesi ya nyumbani"</string>
+ <string name="sms_pager" msgid="7730404569637015192">"Tuma ujumbe kwa peja"</string>
+ <string name="sms_other" msgid="806127844607642331">"Matini"</string>
+ <string name="sms_callback" msgid="5004824430094288752">"Piga simu tena kwa kutumia maandishi"</string>
+ <string name="sms_car" msgid="7444227058437359641">"Tuma ujumbe kwa gari"</string>
+ <string name="sms_company_main" msgid="118970873419678087">"Kampuni kuu ya maandishi"</string>
+ <string name="sms_isdn" msgid="8153785037515047845">"Tuma ujumbe kwa ISDN"</string>
+ <string name="sms_main" msgid="8621625784504541679">"Tuma ujumbe wa simu kuu"</string>
+ <string name="sms_other_fax" msgid="3888842199855843152">"Faksi ya maandishi"</string>
+ <string name="sms_radio" msgid="3329166673433967820">"Tuma ujumbe kwa redio"</string>
+ <string name="sms_telex" msgid="9034802430065267848">"Tuma ujumbe kwa teleksi"</string>
+ <string name="sms_tty_tdd" msgid="6782284969132531532">"Tuma ujumbe kwa TTY/TDD"</string>
+ <string name="sms_work_mobile" msgid="2459939960512702560">"Tuma ujumbe kwa simu ya mkononi ya kazini"</string>
+ <string name="sms_work_pager" msgid="5566924423316960597">"Tuma ujumbe kwa peja ya kazini"</string>
+ <string name="sms_assistant" msgid="2773424339923116234">"Tuma ujumbe kwa <xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="sms_mms" msgid="4069352461380762677">"Tuma maandishi ya MMS"</string>
+ <string name="email_home" msgid="8573740658148184279">"Nyumbani mwa barua pepe"</string>
+ <string name="email_mobile" msgid="2042889209787989814">"Tuma barua pepe kwa simu ya mkononi"</string>
+ <string name="email_work" msgid="2807430017302722689">"Tuma barua pepe kazini"</string>
+ <string name="email_other" msgid="3454004077967657109">"Barua pepe"</string>
+ <string name="email_custom" msgid="7548003991586214105">"Barua pepe <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="email" msgid="5668400997660065897">"Barua pepe"</string>
+ <string name="map_home" msgid="1243547733423343982">"Angalia anwani ya nyumbani"</string>
+ <string name="map_work" msgid="1360474076921878088">"Angalia anwani ya kazini"</string>
+ <string name="map_other" msgid="3817820803587012641">"Tazama anwani"</string>
+ <string name="map_custom" msgid="6184363799976265281">"Angalia anwani <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="chat_aim" msgid="2588492205291249142">"Piga gumzo kwa kutumia AIM"</string>
+ <string name="chat_msn" msgid="8041633440091073484">"Piga gumzo kwa kutumia Windows Live"</string>
+ <string name="chat_yahoo" msgid="6629211142719943666">"Piga gumzo kwa kutumia Yahoo"</string>
+ <string name="chat_skype" msgid="1210045020427480566">"Piga gumzo kwa kutumia Skype"</string>
+ <string name="chat_qq" msgid="4294637812847719693">"Piga gumzo kwa kutumia QQ"</string>
+ <string name="chat_gtalk" msgid="981575737258117697">"Piga gumzo kwa kutumia Google Talk"</string>
+ <string name="chat_icq" msgid="8438405386153745775">"Piga gumzo kwa kutumia ICQ"</string>
+ <string name="chat_jabber" msgid="7561444230307829609">"Piga gumzo kwa kutumia Jabber"</string>
+ <string name="chat" msgid="9025361898797412245">"Gumzo"</string>
+ <string name="postal_address" msgid="8765560217149624536">"Anwani"</string>
+ <string name="postal_street" msgid="8133143961580058972">"Barabara"</string>
+ <string name="postal_pobox" msgid="4431938829180269821">"Sanduku la posta"</string>
+ <string name="postal_neighborhood" msgid="1450783874558956739">"Mtaa"</string>
+ <string name="postal_city" msgid="6597491300084895548">"Jiji"</string>
+ <string name="postal_region" msgid="6045263193478437672">"Jimbo"</string>
+ <string name="postal_postcode" msgid="572136414136673751">"Msimbo wa posta"</string>
+ <string name="postal_country" msgid="7638264508416368690">"Nchi"</string>
+ <string name="full_name" msgid="6602579550613988977">"Jina"</string>
+ <string name="name_given" msgid="1687286314106019813">"Jina la kupewa"</string>
+ <string name="name_family" msgid="3416695586119999058">"Jina la familia"</string>
+ <string name="name_prefix" msgid="59756378548779822">"Kiambishi awali cha jina"</string>
+ <string name="name_middle" msgid="8467433655992690326">"Jina la kati"</string>
+ <string name="name_suffix" msgid="3855278445375651441">"Kiambishi awali cha jina"</string>
+ <string name="name_phonetic_given" msgid="6853570431394449191">"Jina lililotolewa la fonetiki"</string>
+ <string name="name_phonetic_middle" msgid="8643721493320405200">"Jina la katikati la kifonetiki"</string>
+ <string name="name_phonetic_family" msgid="462095502140180305">"Jina la kifonetiki la familia"</string>
+ <!-- no translation found for name_phonetic (4259595234312430484) -->
+ <skip />
+ <string name="account_type_format" msgid="718948015590343010">"Anwani <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
+ <string name="use_photo_as_primary" msgid="8807110122951157246">"Tumia picha hii"</string>
+ <string name="contact_read_only" msgid="1203216914575723978">"Maelezo ya anwani <xliff:g id="SOURCE">%1$s</xliff:g> hayawezi kuhaririwa kwenye kifaa hiki."</string>
+ <string name="no_contact_details" msgid="6754415338321837001">"Hakuna maelezo ya ziada ya anwani hii"</string>
+ <string name="display_options_sort_list_by" msgid="6080091755852211076">"Panga orodha kwa"</string>
+ <string name="display_options_sort_by_given_name" msgid="184916793466387067">"Jina la kwanza"</string>
+ <string name="display_options_sort_by_family_name" msgid="7857986975275712622">"Jila la familia"</string>
+ <string name="display_options_view_names_as" msgid="18022868169627979">"Tazama majina ya anwani kama"</string>
+ <string name="display_options_view_given_name_first" msgid="6968288511197363292">"Jina ulilopewa kwanza"</string>
+ <string name="display_options_view_family_name_first" msgid="1447288164951453714">"Jina la familia kwanza"</string>
+ <string name="search_bar_hint" msgid="1012756309632856553">"Tafuta anwani"</string>
+ <string name="search_for_all_contacts" msgid="6644963335787294131">"Tafuta anwani zote"</string>
+ <string name="take_photo" msgid="7496128293167402354">"Piga picha"</string>
+ <!-- no translation found for take_new_photo (7341354729436576304) -->
+ <skip />
+ <string name="pick_photo" msgid="448886509158039462">"Chagua picha kutoka kwa Matunzio"</string>
+ <!-- no translation found for pick_new_photo (7962368009197147617) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in locale_change_in_progress -->
+ <skip />
+ <!-- no translation found for locale_change_in_progress (7583992153091537467) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in upgrade_in_progress -->
+ <skip />
+ <!-- no translation found for upgrade_in_progress (474511436863451061) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory (6153384328042175667) -->
+ <skip />
+ <string name="upgrade_out_of_memory_uninstall" msgid="1721798828992091432">"Ondoa baadhi ya programu"</string>
+ <string name="upgrade_out_of_memory_retry" msgid="8431289830472724609">"Jaribu kupandisha gredi tena"</string>
+ <string name="search_results_searching" msgid="7755623475227227314">"Inatafuta..."</string>
+ <string name="menu_display_selected" msgid="6470001164297969034">"Onyesha iliyochaguliwa"</string>
+ <string name="menu_display_all" msgid="8887488642609786198">"Onyesha zote"</string>
+ <string name="menu_select_all" msgid="621719255150713545">"Chagua zote"</string>
+ <string name="menu_select_none" msgid="7093222469852132345">"Usichague zote"</string>
+ <plurals name="multiple_picker_title">
+ <item quantity="one" msgid="4761009734586319101">"Mpokeaji 1 alichaguliwa"</item>
+ <item quantity="other" msgid="4608837420986126229">"Wapokeaji <xliff:g id="COUNT">%d</xliff:g> wamechaguliwa"</item>
+ </plurals>
+ <string name="no_contacts_selected" msgid="5877803471037324613">"Hakuna anwani zilizochaguliwa."</string>
+ <!-- no translation found for add_field (2384260056674995230) -->
+ <skip />
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
+ <string name="contact_status_update_attribution" msgid="752179367353018597">"kupitia <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> kupitia <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
+ <string name="description_star" msgid="2605854427360036550">"kipendwa"</string>
+ <string name="edit_contact" msgid="7529281274005689512">"Hariri anwani"</string>
+ <plurals name="merge_info">
+ <item quantity="one" msgid="148365587896371969">"haijaunganishwa"</item>
+ <item quantity="other" msgid="425683718017380845">"Zimeunganishwa kutoka kwa nyenzo <xliff:g id="COUNT">%0$d</xliff:g>"</item>
+ </plurals>
+ <string name="local_invisible_directory" msgid="6046691709127661065">"Nyingineyo"</string>
+ <!-- no translation found for aggregation_suggestion_join_dialog_title (5276699501316246253) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_message (3842757977671434836) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_title (1064042382692091314) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_message (6549585283910518095) -->
+ <skip />
+ <string name="menu_copyContact" msgid="4401683725471696686">"Nakili kwa anwani zangu"</string>
+ <!-- no translation found for contact_directory_description (683398073603909119) -->
+ <skip />
+ <!-- no translation found for search_label (6789295859496641042) -->
+ <skip />
+ <string name="directory_search_label" msgid="1887759056597975053">"Saraka"</string>
+ <string name="local_search_label" msgid="1686089693064201315">"Anwani"</string>
+ <string name="toast_making_personal_copy" msgid="7905283986345263275">"Inaunda nakala ya kibinafsi"</string>
+ <string name="list_filter_prompt" msgid="7481426622828055116">"Chagua orodha ya anwani"</string>
+ <string name="list_filter_all_accounts" msgid="8908683398914322369">"Anwani zote"</string>
+ <!-- no translation found for list_filter_all_starred (5031734941601931356) -->
+ <skip />
+ <!-- no translation found for list_filter_custom (8910173055702057002) -->
+ <skip />
+ <string name="list_filter_customize" msgid="2035084418635775579">"Geuza kukufaa..."</string>
+ <!-- no translation found for list_filter_phones (7905045603593508221) -->
+ <skip />
+ <!-- no translation found for list_filter_single (5871400283515893087) -->
+ <skip />
+ <!-- no translation found for custom_list_filter (7836035257402013957) -->
+ <skip />
+ <string name="activity_title_settings" msgid="5464130076132770781">"Mipangilio"</string>
+ <string name="menu_settings" msgid="377929915873428211">"Mipangilio"</string>
+ <string name="preference_displayOptions" msgid="1341720270148252393">"Onyesha machaguo"</string>
+ <!-- no translation found for organization_company_and_title (6718207751363732025) -->
+ <skip />
+ <!-- no translation found for hint_findContacts (1808681193458772072) -->
+ <skip />
+ <!-- no translation found for non_phone_caption (1541655052330027380) -->
+ <skip />
+ <!-- no translation found for non_phone_add_to_contacts (6590985286250471169) -->
+ <skip />
+ <!-- no translation found for non_phone_close (7608506439725515667) -->
+ <skip />
+ <!-- no translation found for widget_name_and_phonetic (8739586586600099979) -->
+ <skip />
+ <!-- no translation found for date_year_toggle (7356532842767854606) -->
+ <skip />
+ <!-- no translation found for social_widget_label (6378905543028924592) -->
+ <skip />
+ <!-- no translation found for social_widget_loading (3697996166985327861) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_create_contact (7014525713871959208) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_add_account (7911101713860139754) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_import_contacts (4456440183590517471) -->
+ <skip />
+ <!-- no translation found for create_group_dialog_title (6874527142828424475) -->
+ <skip />
+ <!-- no translation found for create_group_item_label (5218022006186243310) -->
+ <skip />
+ <!-- no translation found for rename_group_dialog_title (3765299704290513289) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_title (7368429698398624427) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_message (295063284548750881) -->
+ <skip />
+ <!-- no translation found for toast_join_with_empty_contact (5015189525953438968) -->
+ <skip />
+ <!-- no translation found for indicator_joined_contact (3321049349627022128) -->
+ <skip />
+ <!-- no translation found for toast_text_copied (5143776250008541719) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_title (3950463632415908534) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_message (7021968394611740251) -->
+ <skip />
+ <!-- no translation found for discard (1234315037371251414) -->
+ <skip />
+</resources>
diff --git a/res/values-sw580dp-w720dp/dimens.xml b/res/values-sw580dp-w720dp/dimens.xml
deleted file mode 100644
index 399c26c..0000000
--- a/res/values-sw580dp-w720dp/dimens.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources>
- <dimen name="editor_type_label_width">180dip</dimen>
- <dimen name="editor_round_button_padding_left">8dip</dimen>
- <dimen name="editor_round_button_padding_right">8dip</dimen>
- <dimen name="editor_name_text_field_left_margin">52dip</dimen>
- <dimen name="editor_title_label_width">150dip</dimen>
- <dimen name="editor_interpolator_narrow_width">800dip</dimen>
- <dimen name="editor_name_text_field_right_margin">10dip</dimen>
-</resources>
diff --git a/res/values-sw580dp-w720dp/styles.xml b/res/values-sw580dp-w720dp/styles.xml
deleted file mode 100644
index c01ef25..0000000
--- a/res/values-sw580dp-w720dp/styles.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<resources>
- <style name="ContactBrowserTheme" parent="@android:Theme.Holo.Light">
- <item name="list_item_height">66dip</item>
- <item name="activated_background">@drawable/list_item_activated_background</item>
- <item name="android:windowContentOverlay">@null</item>
- <item name="android:actionBarStyle">@style/TransparentActionBarStyle</item>
- <item name="section_header_background">@drawable/list_title_holo</item>
- <item name="list_item_divider">?android:attr/listDivider</item>
- <item name="list_item_padding_top">0dip</item>
- <item name="list_item_padding_right">24dip</item>
- <item name="list_item_padding_bottom">0dip</item>
- <item name="list_item_padding_left">0dip</item>
- <item name="list_item_fading_edge_length">5dip</item>
- <item name="list_item_gap_between_image_and_text">16dip</item>
- <item name="list_item_gap_between_label_and_data">5dip</item>
- <item name="list_item_call_button_padding">14dip</item>
- <item name="list_item_vertical_divider_margin">5dip</item>
- <item name="list_item_presence_icon_margin">30dip</item>
- <item name="list_item_photo_size">64dip</item>
- <item name="list_item_prefix_highlight_color">#729a27</item>
- <item name="list_item_header_text_indent">77dip</item>
- <item name="list_item_header_text_color">?color/section_header_text_color</item>
- <item name="list_item_header_text_size">14sp</item>
- <item name="contact_filter_popup_width">320dip</item>
- </style>
-
- <style name="ContactDetailHeaderTextView">
- <item name="android:layout_width">match_parent</item>
- <item name="android:layout_height">wrap_content</item>
- <item name="android:singleLine">true</item>
- <item name="android:ellipsize">end</item>
- </style>
-</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 595cfcc..3ebf255 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"เริ่มต้น"</string>
<string name="removePhoto" msgid="4898105274130284565">"นำภาพออก"</string>
<string name="noContacts" msgid="8579310973261953559">"ไม่มีรายชื่อ"</string>
+ <string name="noGroups" msgid="8614664663561385253">"ไม่มีกลุ่ม"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"ไม่พบรายชื่อที่ตรงกัน"</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"ไม่รายชื่อที่มีหมายเลขโทรศัพท์"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"เฉพาะรายชื่อที่มีหมายเลขโทรศัพท์"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"พบ <xliff:g id="COUNT">%d</xliff:g> รายการ"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"รายชื่อ"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"กลุ่ม"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"รายการโปรด"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"โทรศัพท์"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"บันทึกการโทร"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"บันทึกการโทรว่างเปล่า"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"ล้างบันทึกการโทร"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"คุณแน่ใจหรือไม่ว่าต้องการล้างบันทึกการโทรทั้งหมด"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"การล้างบันทึกการโทร"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"ข้อความเสียง"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"ไม่พบการ์ด SD"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"กำลังค้นหา vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"นำเข้าจากซิมการ์ด"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"นำเข้าจากที่เก็บข้อมูล"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"ส่งออกไปยังที่เก็บข้อมูล"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"นำเข้าจากที่เก็บข้อมูล"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"นำเข้าจากการ์ด SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"ส่งออกไปยังที่เก็บข้อมูล"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"ส่งออกไปยังการ์ด SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"แบ่งปันสมุดโทรศัพท์ที่มองเห็น"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"นำเข้าไฟล์ vCard หนึ่งไฟล์"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"นำเข้าไฟล์ vCard หลายไฟล์"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"นามสกุลแบบออกเสียง"</string>
<string name="name_phonetic" msgid="4259595234312430484">"ชื่อแบบออกเสียง"</string>
<string name="account_type_format" msgid="718948015590343010">"รายชื่อในสมุดโทรศัพท์จาก <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"จาก <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"ใช้ภาพนี้"</string>
<string name="contact_read_only" msgid="1203216914575723978">"ข้อมูลรายชื่อของ <xliff:g id="SOURCE">%1$s</xliff:g> แก้ไขบนอุปกรณ์นี้ไม่ได้"</string>
<string name="no_contact_details" msgid="6754415338321837001">"ไม่มีข้อมูลเพิ่มเติมสำหรับรายชื่อนี้"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"ไม่ได้เลือกสมุดโทรศัพท์ไว้"</string>
<string name="add_field" msgid="2384260056674995230">"เพิ่มฟิลด์อื่น"</string>
+ <string name="add_phone" msgid="4421904942555210013">"เพิ่มหมายเลขโทรศัพท์ใหม่"</string>
+ <string name="add_email" msgid="175079666329862215">"เพิ่มอีเมลใหม่"</string>
+ <string name="add_im" msgid="5158094627521120439">"เพิ่มบัญชี IM ใหม่"</string>
+ <string name="add_address" msgid="418292312672970688">"เพิ่มที่อยู่ใหม่"</string>
+ <string name="add_note" msgid="2753771325725383279">"เพิ่มบันทึกใหม่"</string>
+ <string name="add_website" msgid="4312391288948517344">"เพิ่มเว็บไซต์ใหม่"</string>
+ <string name="add_event" msgid="7488781591843886426">"เพิ่มกิจกรรมใหม่"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"เพิ่มความเกี่ยวข้องใหม่"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"ผ่านทาง <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> ผ่านทาง <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"รายการโปรด"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 0d9cb5a..dc6fd9a 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Default"</string>
<string name="removePhoto" msgid="4898105274130284565">"Alisin ang larawan"</string>
<string name="noContacts" msgid="8579310973261953559">"Walang mga contact."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Walang mga pangkat."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Walang nakitang magkakatugmang mga contact."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Walang mga contact na may mga numero ng telepono."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Mga contact lang na may mga telepono"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> ang nakita"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Mga Contact"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Mga Pangkat"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Mga Paborito"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telepono"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Log ng tawag"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Walang laman ang log ng tawag."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"I-clear ang log ng tawag"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Sigurado ka bang gusto mong i-clear ang log ng tawag?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Kini-clear ang log ng tawag"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Voicemail"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Walang natukoy na SD card"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Paghahanap ng vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"I-import mula sa SIM card"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"I-import mula sa imbakan"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"I-export sa imbakan"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"I-import mula sa imbakan"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Mag-import mula sa SD card"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"I-export sa imbakan"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Mag-export sa SD card"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Magbahagi ng mga nakikitang contact"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Mag-import nang isang vCard file"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Mag-import ng maramihang vCard file"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Phonetic na apelyido"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Phonetic na pangalan"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> contact"</string>
- <string name="from_account_format" msgid="687567483928582084">"mula sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Gamitin ang larawang ito"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Ang impormasyon sa contact ng <xliff:g id="SOURCE">%1$s</xliff:g> ay hindi nae-edit sa device na ito."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Walang karagdagang impormasyon para sa contact na ito"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Walang napiling contact."</string>
<string name="add_field" msgid="2384260056674995230">"Magdagdag ng ibang field"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Magdagdag ng bagong numero ng telepono"</string>
+ <string name="add_email" msgid="175079666329862215">"Magdagdag ng bagong email"</string>
+ <string name="add_im" msgid="5158094627521120439">"Magdagdag ng bagong IM account"</string>
+ <string name="add_address" msgid="418292312672970688">"Magdagdag ng bagong address"</string>
+ <string name="add_note" msgid="2753771325725383279">"Magdagdag ng bagong paalala"</string>
+ <string name="add_website" msgid="4312391288948517344">"Magdagdag ng bagong website"</string>
+ <string name="add_event" msgid="7488781591843886426">"Magdagdag ng bagong kaganapan"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Magdagdag ng bagong ugnayan"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"sa pamamagitan ng <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> sa pamamagitan ng <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"paborito"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 8241f9e..2fb3d93 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Varsayılan"</string>
<string name="removePhoto" msgid="4898105274130284565">"Fotoğrafı kaldır"</string>
<string name="noContacts" msgid="8579310973261953559">"Hiçbir kişi yok."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Grup yok."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Eşleşen kişi bulunamadı."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Telefon numarası olan hiçbir kişi yok."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Yalnızca telefonu olan kişiler"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> kişi bulundu"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Kişiler"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Gruplar"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Sık Kullanılanlar"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Telefon"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Çağrı kaydı"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Çağrı kaydı boş."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Çağrı kaydını temizle"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Çağrı kaydını silmek istediğinizden emin misiniz?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Çağrı kaydı temizleniyor"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Sesli Mesaj"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Hiçbir SD kart tespit edilmedi"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"vCard aranıyor"</string>
<string name="import_from_sim" msgid="3859272228033941659">"SIM karttan içe aktar"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Depl biriminden içe aktar"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Depolama birimine aktar"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Depl biriminden içe aktar"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"SD karttan içe aktar"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Depolama birimine aktar"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"SD karta dışa aktar"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Görülebilir kişileri paylaş"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Bir vCard dosyasını içe aktar"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Birden fazla vCard dosyasını içe aktar"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Fonetik soyadı"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Fonetik ad"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> kişi"</string>
- <string name="from_account_format" msgid="687567483928582084">"kaynak: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Bu fotoğrafı kullan"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> kişi bilgileri bu cihazda düzenlenemez."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Bu kişi için ek bilgi yok"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Seçili kişi yok."</string>
<string name="add_field" msgid="2384260056674995230">"Başka alan ekle"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Yeni tel no ekle"</string>
+ <string name="add_email" msgid="175079666329862215">"Yeni e-posta ekle"</string>
+ <string name="add_im" msgid="5158094627521120439">"Yeni IM hesabı ekle"</string>
+ <string name="add_address" msgid="418292312672970688">"Yeni adres ekle"</string>
+ <string name="add_note" msgid="2753771325725383279">"Yeni not ekle"</string>
+ <string name="add_website" msgid="4312391288948517344">"Yeni web sitesi ekle"</string>
+ <string name="add_event" msgid="7488781591843886426">"Yeni etkinlik ekle"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Yeni ilişki ekle"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"<xliff:g id="SOURCE">%1$s</xliff:g> aracılığıyla"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="SOURCE">%2$s</xliff:g> üzerinden şu saatte: <xliff:g id="DATE">%1$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"favori"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 1e889e2..83568ef 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"За умовч."</string>
<string name="removePhoto" msgid="4898105274130284565">"Видалити фото"</string>
<string name="noContacts" msgid="8579310973261953559">"Немає контакт."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Немає груп."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Не знайдено відпов. контактів."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Немає контактів з номерами тел."</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Лише контакти з ном. тел."</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Знайдено <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Контакти"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Групи"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Вибране"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Тел."</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Журн. викл."</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Журн. викл. порожній."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Очист. журнал викл."</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Дійсно очистити журнал викликів?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Очищення журналу викликів"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Голос. пошта"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Карту SD не виявлено"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Пошук даних vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Імортув. з SIM-карти"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Імпорт із пам’яті"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Експорт у пам’ять"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Імпорт із пам’яті"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Імортув. з карти SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Експорт у пам’ять"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Експорт. на карту SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Надісл. видимі контакти"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Імпортув. 1 файл vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Імпортув. кілька файлів vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Вимова прізвища"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Вимова імені"</string>
<string name="account_type_format" msgid="718948015590343010">"Контакт <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"з <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Викор. це фото"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Конт. інф-цію <xliff:g id="SOURCE">%1$s</xliff:g> неможливо редагув. на цьому пристрої."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Немає додатк. інформації для цього контакту"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Контакти не вибрано."</string>
<string name="add_field" msgid="2384260056674995230">"Додати ще одне поле"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Додати нов. номер тел."</string>
+ <string name="add_email" msgid="175079666329862215">"Додати нову ел. адресу"</string>
+ <string name="add_im" msgid="5158094627521120439">"Дод. нов.обл.зап. чату"</string>
+ <string name="add_address" msgid="418292312672970688">"Додати нову адресу"</string>
+ <string name="add_note" msgid="2753771325725383279">"Додати нову примітку"</string>
+ <string name="add_website" msgid="4312391288948517344">"Додати новий веб-сайт"</string>
+ <string name="add_event" msgid="7488781591843886426">"Додати нову подію"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Додати нові стосунки"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"через <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> через <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"вибране"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 8930625..7571f61 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"Mặc định"</string>
<string name="removePhoto" msgid="4898105274130284565">"Xóa ảnh"</string>
<string name="noContacts" msgid="8579310973261953559">"Không có liên hệ nào."</string>
+ <string name="noGroups" msgid="8614664663561385253">"Không có nhóm nào."</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"Không tìm thấy liên hệ nào phù hợp."</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"Không có liên hệ nào có số điện thoại"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"Chỉ các liên hệ có số điện thoại"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"Đã tìm thấy <xliff:g id="COUNT">%d</xliff:g>"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"Danh bạ"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"Nhóm"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"Mục ưa thích"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"Điện thoại"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"Nhật ký cuộc gọi"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"Nhật ký cuộc gọi trống."</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Xoá nhật ký cuộc gọi"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"Bạn có chắc chắn muốn xoá nhật ký cuộc gọi không?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"Đang xóa nhật ký cuộc gọi"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"Thư thoại"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Không phát hiện thẻ SD nào"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"Đang tìm kiếm vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"Nhập từ thẻ SIM"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"Nhập từ bộ nhớ"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"Xuất sang bộ nhớ"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Nhập từ bộ nhớ"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Nhập từ thẻ SD"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Xuất sang bộ nhớ"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Xuất sang thẻ SD"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"Chia sẻ liên hệ hiển thị"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"Nhập một tệp vCard"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"Nhập nhiều tệp vCard"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"Họ đúng phát âm"</string>
<string name="name_phonetic" msgid="4259595234312430484">"Tên theo phiên âm"</string>
<string name="account_type_format" msgid="718948015590343010">"Liên hệ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
- <string name="from_account_format" msgid="687567483928582084">"từ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"Sử dụng ảnh này"</string>
<string name="contact_read_only" msgid="1203216914575723978">"Không thể chỉnh sửa thông tin liên hệ <xliff:g id="SOURCE">%1$s</xliff:g> trên thiết bị này."</string>
<string name="no_contact_details" msgid="6754415338321837001">"Không có thông tin bổ sung cho liên hệ này"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"Không có địa chỉ liên hệ nào được chọn."</string>
<string name="add_field" msgid="2384260056674995230">"Thêm trường khác"</string>
+ <string name="add_phone" msgid="4421904942555210013">"Thêm số điện thoại mới"</string>
+ <string name="add_email" msgid="175079666329862215">"Thêm email mới"</string>
+ <string name="add_im" msgid="5158094627521120439">"Thêm tài khoản IM mới"</string>
+ <string name="add_address" msgid="418292312672970688">"Thêm địa chỉ mới"</string>
+ <string name="add_note" msgid="2753771325725383279">"Thêm chú thích mới"</string>
+ <string name="add_website" msgid="4312391288948517344">"Thêm trang web mới"</string>
+ <string name="add_event" msgid="7488781591843886426">"Thêm sự kiện mới"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"Thêm mối quan hệ mới"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">" qua <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> qua <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"Yêu thích"</string>
diff --git a/res/values-sw580dp-w1000dp/dimens.xml b/res/values-xlarge-land/dimens.xml
similarity index 88%
rename from res/values-sw580dp-w1000dp/dimens.xml
rename to res/values-xlarge-land/dimens.xml
index 45da0a8..52c521e 100644
--- a/res/values-sw580dp-w1000dp/dimens.xml
+++ b/res/values-xlarge-land/dimens.xml
@@ -19,6 +19,4 @@
<dimen name="action_bar_filter_max_width">300dip</dimen>
<dimen name="action_bar_search_max_width">336dip</dimen>
<dimen name="action_bar_search_spacing">32dip</dimen>
- <dimen name="detail_header_view_margin">16dip</dimen>
- <dimen name="detail_header_attribution_height">56dip</dimen>
</resources>
diff --git a/res/values-sw580dp/colors.xml b/res/values-xlarge/colors.xml
similarity index 100%
rename from res/values-sw580dp/colors.xml
rename to res/values-xlarge/colors.xml
diff --git a/res/values-sw580dp/dimens.xml b/res/values-xlarge/dimens.xml
similarity index 71%
rename from res/values-sw580dp/dimens.xml
rename to res/values-xlarge/dimens.xml
index d29eba2..2d39186 100644
--- a/res/values-sw580dp/dimens.xml
+++ b/res/values-xlarge/dimens.xml
@@ -16,6 +16,13 @@
<resources>
<dimen name="edit_photo_size">96dip</dimen>
<dimen name="aggregation_suggestion_icon_size">64dip</dimen>
+ <dimen name="editor_type_label_width">180dip</dimen>
+ <dimen name="editor_field_spinner_text_size">15sp</dimen>
+ <dimen name="editor_round_button_padding_left">8dip</dimen>
+ <dimen name="editor_round_button_padding_right">8dip</dimen>
+ <dimen name="editor_field_top_padding">12dip</dimen>
+ <dimen name="editor_field_bottom_padding">12dip</dimen>
+ <dimen name="detail_item_side_margin">19dip</dimen>
<dimen name="quick_contact_width">356dip</dimen>
<dimen name="contact_name_text_size">26sp</dimen>
<dimen name="action_bar_filter_min_width">120dip</dimen>
@@ -23,4 +30,5 @@
<dimen name="action_bar_search_max_width">300dip</dimen>
<dimen name="action_bar_search_spacing">12dip</dimen>
<dimen name="shortcut_icon_size">64dip</dimen>
+ <dimen name="list_section_height">37dip</dimen>
</resources>
diff --git a/res/values-xlarge/donottranslate_config.xml b/res/values-xlarge/donottranslate_config.xml
new file mode 100644
index 0000000..fcb7da9
--- /dev/null
+++ b/res/values-xlarge/donottranslate_config.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <bool name="config_use_two_panes">true</bool>
+</resources>
diff --git a/res/values-sw580dp/styles.xml b/res/values-xlarge/styles.xml
similarity index 83%
rename from res/values-sw580dp/styles.xml
rename to res/values-xlarge/styles.xml
index 4e5fda6..d44d993 100644
--- a/res/values-sw580dp/styles.xml
+++ b/res/values-xlarge/styles.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<resources>
- <style name="ContactBrowserTheme" parent="@android:Theme.Holo.Light">
+ <style name="PeopleTheme" parent="@android:Theme.Holo.Light">
<item name="list_item_height">66dip</item>
<item name="activated_background">@drawable/list_item_activated_background</item>
<item name="android:windowContentOverlay">@null</item>
@@ -22,15 +22,14 @@
<item name="section_header_background">@drawable/list_title_holo</item>
<item name="list_item_divider">?android:attr/listDivider</item>
<item name="list_item_padding_top">0dip</item>
- <item name="list_item_padding_right">20dip</item>
+ <item name="list_item_padding_right">24dip</item>
<item name="list_item_padding_bottom">0dip</item>
<item name="list_item_padding_left">0dip</item>
- <item name="list_item_fading_edge_length">5dip</item>
- <item name="list_item_gap_between_image_and_text">8dip</item>
+ <item name="list_item_gap_between_image_and_text">16dip</item>
<item name="list_item_gap_between_label_and_data">5dip</item>
<item name="list_item_call_button_padding">14dip</item>
<item name="list_item_vertical_divider_margin">5dip</item>
- <item name="list_item_presence_icon_margin">18dip</item>
+ <item name="list_item_presence_icon_margin">30dip</item>
<item name="list_item_photo_size">64dip</item>
<item name="list_item_prefix_highlight_color">#729a27</item>
<item name="list_item_header_text_indent">77dip</item>
@@ -58,15 +57,12 @@
<item name="list_item_header_text_size">14sp</item>
</style>
- <style name="ContactsPreferencesTheme" parent="@android:Theme.Holo.Light">
- </style>
-
<style name="CustomContactListFilterTheme" parent="@android:Theme.Holo.Light.Dialog">
</style>
<style name="CustomContactListFilterView" parent="CustomContactListFilterTheme">
<item name="android:layout_width">400dip</item>
- <item name="android:layout_height">400dip</item>
+ <item name="android:layout_height">600dip</item>
</style>
<style name="ContactPickerLayout" parent="ContactPickerTheme">
@@ -91,7 +87,7 @@
<item name="android:background">@null</item>
</style>
- <style name="DirectoryHeader" parent="ContactBrowserTheme">
+ <style name="DirectoryHeader" parent="PeopleTheme">
<item name="android:background">@drawable/directory_bg_holo</item>
</style>
@@ -106,4 +102,15 @@
<item name="android:windowNoDisplay">true</item>
<item name="android:windowIsFloating">true</item>
</style>
+
+ <style name="ContactDetailItemType">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:textColor">@color/detail_item_type_color</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:ellipsize">marquee</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:paddingTop">5dip</item>
+ </style>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f4fff14..d04c2ce 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"默认日历"</string>
<string name="removePhoto" msgid="4898105274130284565">"删除照片"</string>
<string name="noContacts" msgid="8579310973261953559">"没有联系人。"</string>
+ <string name="noGroups" msgid="8614664663561385253">"没有任何群组。"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"未找到匹配的联系人。"</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"没有联系人拥有电话号码。"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"仅显示有电话号码的联系人"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"找到 <xliff:g id="COUNT">%d</xliff:g> 个联系人"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"通讯录"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"群组"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"收藏"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"拨号"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"通话记录"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"通话记录为空。"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"清除通话记录"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"确定要清除通话记录吗?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"正在清除通话记录"</string>
<string name="imei" msgid="3045126336951684285">"移动通信国际识别码"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"语音信箱"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"未检测到 SD 卡"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"正在搜索 vCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"从 SIM 卡导入"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"从存储设备导入"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"导出到存储设备"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"从存储设备导入"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"从 SD 卡导入"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"导出到存储设备"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"导出到 SD 卡"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"分享可见的联系人"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"导入一个 vCard 文件"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"导入多个 vCard 文件"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"姓氏拼音"</string>
<string name="name_phonetic" msgid="4259595234312430484">"姓名拼音"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> 联系人"</string>
- <string name="from_account_format" msgid="687567483928582084">"来自 <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"使用此照片"</string>
<string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> 联系人信息在此设备上不可编辑。"</string>
<string name="no_contact_details" msgid="6754415338321837001">"无此联系人的其他信息"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"未选择联系人。"</string>
<string name="add_field" msgid="2384260056674995230">"添加其他字段"</string>
+ <string name="add_phone" msgid="4421904942555210013">"添加新电话号码"</string>
+ <string name="add_email" msgid="175079666329862215">"添加新电子邮件地址"</string>
+ <string name="add_im" msgid="5158094627521120439">"添加新即时通讯帐户"</string>
+ <string name="add_address" msgid="418292312672970688">"添加新地址"</string>
+ <string name="add_note" msgid="2753771325725383279">"添加新备注"</string>
+ <string name="add_website" msgid="4312391288948517344">"添加新网站"</string>
+ <string name="add_event" msgid="7488781591843886426">"添加新活动"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"添加新关系"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"来源:<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"时间:<xliff:g id="DATE">%1$s</xliff:g>,来源:<xliff:g id="SOURCE">%2$s</xliff:g>"</string>
<string name="description_star" msgid="2605854427360036550">"收藏"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 10c82a4..57a75e5 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -95,6 +95,7 @@
<string name="default_ringtone" msgid="9099988849649827972">"預設值"</string>
<string name="removePhoto" msgid="4898105274130284565">"移除相片"</string>
<string name="noContacts" msgid="8579310973261953559">"沒有聯絡人。"</string>
+ <string name="noGroups" msgid="8614664663561385253">"沒有群組。"</string>
<string name="noMatchingContacts" msgid="4266283206853990471">"找不到符合的聯絡人。"</string>
<string name="noContactsWithPhoneNumbers" msgid="1605457050218824269">"沒有包含電話號碼的聯絡人資訊。"</string>
<string name="showFilterPhones" msgid="4184858075465653970">"僅顯示有電話號碼的聯絡人"</string>
@@ -134,6 +135,7 @@
<item quantity="other" msgid="7988132539476575389">"找到 <xliff:g id="COUNT">%d</xliff:g> 位聯絡人"</item>
</plurals>
<string name="contactsIconLabel" msgid="7666609097606552806">"聯絡人"</string>
+ <string name="contactsGroupsLabel" msgid="2841971472518003524">"群組"</string>
<string name="contactsFavoritesLabel" msgid="8417039765586853670">"我的最愛"</string>
<string name="dialerIconLabel" msgid="6500826552823403796">"電話"</string>
<string name="recentCallsIconLabel" msgid="1419116422359067949">"通話記錄"</string>
@@ -149,6 +151,7 @@
<string name="recentCalls_empty" msgid="247053222448663107">"無通話記錄。"</string>
<string name="clearCallLogConfirmation_title" msgid="718072843006222703">"清除通話記錄"</string>
<string name="clearCallLogConfirmation" msgid="7625927669136267636">"確定要清除通話記錄嗎?"</string>
+ <string name="clearCallLogProgress_title" msgid="6870412675015656948">"正在清除通話記錄"</string>
<string name="imei" msgid="3045126336951684285">"IMEI"</string>
<string name="meid" msgid="6210568493746275750">"MEID"</string>
<string name="voicemail" msgid="3851469869202611441">"語音留言"</string>
@@ -214,8 +217,10 @@
<string name="no_sdcard_message" product="default" msgid="6019391476490445358">"未偵測到 SD 卡"</string>
<string name="searching_vcard_title" msgid="4970508055399376813">"正在搜尋 VCard"</string>
<string name="import_from_sim" msgid="3859272228033941659">"從 SIM 卡匯入"</string>
- <string name="import_from_sdcard" product="default" msgid="8668347930577565175">"從儲存裝置匯入"</string>
- <string name="export_to_sdcard" product="default" msgid="6092815580965201089">"匯出到儲存裝置"</string>
+ <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"從儲存裝置匯入"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"從 SD 卡匯入"</string>
+ <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"匯出到儲存裝置"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"匯出至 SD 卡"</string>
<string name="share_visible_contacts" msgid="890150378880783797">"分享正常顯示的聯絡人"</string>
<string name="import_one_vcard_string" msgid="9059163467020328433">"匯入一個 vCard 檔案"</string>
<string name="import_multiple_vcard_string" msgid="3810226492811062392">"匯入多個 vCard 檔案"</string>
@@ -397,7 +402,8 @@
<string name="name_phonetic_family" msgid="462095502140180305">"姓氏 (拼音)"</string>
<string name="name_phonetic" msgid="4259595234312430484">"姓名拼音"</string>
<string name="account_type_format" msgid="718948015590343010">"<xliff:g id="SOURCE">%1$s</xliff:g> 聯絡人"</string>
- <string name="from_account_format" msgid="687567483928582084">"來自 <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
<string name="use_photo_as_primary" msgid="8807110122951157246">"使用此相片"</string>
<string name="contact_read_only" msgid="1203216914575723978">"無法在此裝置編輯 <xliff:g id="SOURCE">%1$s</xliff:g> 的聯絡人資訊"</string>
<string name="no_contact_details" msgid="6754415338321837001">"沒有此聯絡人的其他資訊"</string>
@@ -429,6 +435,14 @@
</plurals>
<string name="no_contacts_selected" msgid="5877803471037324613">"未選取任何聯絡人。"</string>
<string name="add_field" msgid="2384260056674995230">"新增其他欄位"</string>
+ <string name="add_phone" msgid="4421904942555210013">"新增電話號碼"</string>
+ <string name="add_email" msgid="175079666329862215">"新增電子郵件"</string>
+ <string name="add_im" msgid="5158094627521120439">"新增即時通訊帳戶"</string>
+ <string name="add_address" msgid="418292312672970688">"新增地址"</string>
+ <string name="add_note" msgid="2753771325725383279">"新增附註"</string>
+ <string name="add_website" msgid="4312391288948517344">"新增網站"</string>
+ <string name="add_event" msgid="7488781591843886426">"新增活動"</string>
+ <string name="add_relationship" msgid="3083762399737240006">"新增關係"</string>
<string name="contact_status_update_attribution" msgid="752179367353018597">"透過 <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> (透過 <xliff:g id="SOURCE">%2$s</xliff:g>)"</string>
<string name="description_star" msgid="2605854427360036550">"我的最愛"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
new file mode 100644
index 0000000..ee2b0b5
--- /dev/null
+++ b/res/values-zu/strings.xml
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="sharedUserLabel" msgid="7965035505237135241">"Izinhlelo Zokusebenza ze-Android Core"</string>
+ <!-- no translation found for contactsList (8661624236494819731) -->
+ <skip />
+ <string name="launcherDialer" msgid="8636288196618486553">"Ifoni"</string>
+ <!-- no translation found for shortcutContact (749243779392912958) -->
+ <skip />
+ <string name="shortcutDialContact" msgid="746622101599186779">"Ukudayela okuqondile"</string>
+ <string name="shortcutMessageContact" msgid="2460337253595976198">"Umyalezo oqondile"</string>
+ <string name="shortcutActivityTitle" msgid="6642877210643565436">"Khetha isinqamuleli sothintana naye"</string>
+ <string name="callShortcutActivityTitle" msgid="6065749861423648991">"Khetha inombolo ozoyishayela"</string>
+ <string name="messageShortcutActivityTitle" msgid="3084542316620335911">"Khetha inombolo kumyalezo"</string>
+ <!-- no translation found for contactPickerActivityTitle (6886592363525235031) -->
+ <skip />
+ <!-- no translation found for starredList (4817256136413959463) -->
+ <skip />
+ <!-- no translation found for frequentList (7154768136473953056) -->
+ <skip />
+ <!-- no translation found for strequentList (5640192862059373511) -->
+ <skip />
+ <!-- no translation found for viewContactTitle (7989394521836644384) -->
+ <skip />
+ <!-- no translation found for viewContactDesription (214186610887547860) -->
+ <skip />
+ <!-- no translation found for editContactDescription (2947202828256214947) -->
+ <skip />
+ <!-- no translation found for insertContactDescription (4709878105452681987) -->
+ <skip />
+ <!-- no translation found for searchHint (8482945356247760701) -->
+ <skip />
+ <string name="menu_search" msgid="9147752853603483719">"Sesha"</string>
+ <!-- no translation found for menu_newContact (1209922412763274638) -->
+ <skip />
+ <!-- no translation found for menu_viewContact (2795575601596468581) -->
+ <skip />
+ <string name="menu_callNumber" msgid="5142851348489387516">"Shayela <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for menu_addStar (2908478235715404876) -->
+ <skip />
+ <!-- no translation found for menu_removeStar (5844227078364227030) -->
+ <skip />
+ <!-- no translation found for menu_editContact (3452858480713561396) -->
+ <skip />
+ <!-- no translation found for menu_deleteContact (1916555454274101750) -->
+ <skip />
+ <string name="menu_call" msgid="3992595586042260618">"Shayela othintana naye"</string>
+ <string name="menu_sendSMS" msgid="5535886767547006515">"Bhalela othintana naye"</string>
+ <string name="menu_makeDefaultEmail" msgid="2599044610375789994">"Yenza i-imeyili ezenzakalelayo"</string>
+ <string name="menu_splitAggregate" msgid="8368636463748691868">"Hlukanisa"</string>
+ <!-- no translation found for menu_renameGroup (2798886925154156075) -->
+ <skip />
+ <!-- no translation found for menu_deleteGroup (644571524292675446) -->
+ <skip />
+ <!-- no translation found for menu_new_contact_action_bar (8887818026717394343) -->
+ <skip />
+ <string name="splitConfirmation_title" msgid="6716467920283502570">"Othintana naye ohlukanyisiwe"</string>
+ <string name="splitConfirmation" msgid="1150797297503944823">"Uqinisekile ukuba ufuna ukwehlukanisa lona othintana naye oyedwa abe othintana nabo abaningi: oyedwa weqoqo ngalinye lokwaziswa kothintana naye lokho okuhlanganiswe kukho?"</string>
+ <string name="menu_joinAggregate" msgid="5027981918265667970">"Hlanganisa"</string>
+ <string name="titleJoinContactDataWith" msgid="7684875775798635354">"Joyina othintana nabo"</string>
+ <string name="blurbJoinContactDataWith" msgid="995870557595050304">" Khetha othintana naye ofuna ukumuhlanganisa ne-<xliff:g id="NAME">%s</xliff:g>."</string>
+ <string name="showAllContactsJoinItem" msgid="2189695051430392383">"Bonakalisa bonke othintana nabo"</string>
+ <string name="separatorJoinAggregateSuggestions" msgid="2831414448851313345">"Othintana nabo abasikiselwayo"</string>
+ <string name="separatorJoinAggregateAll" msgid="7939932265026181043">"Bonke othintana nabo"</string>
+ <string name="contactsJoinedMessage" msgid="7208148163607047389">"Othintana nabo abahlanganisiwe"</string>
+ <string name="menu_contactOptions" msgid="1957061455705020617">"Okukhethwa kukho"</string>
+ <string name="contactOptionsTitle" msgid="8259347644090700915">"Okukhethwa kukho"</string>
+ <!-- no translation found for deleteConfirmation_title (6394309508930335204) -->
+ <skip />
+ <string name="readOnlyContactWarning" msgid="1390849295342594265">"Awukwazi ukususa othintana nabo ema-akhawuntini okufunda kuphela, kodwa unabafihla ohlwini lwakho lothintana nabo."</string>
+ <string name="readOnlyContactDeleteConfirmation" msgid="2137170726670196909">"Lona othintana naye uqukethe ulwazi olusuka ema-akhawuntini amaningi. Ukwaziswa okusuka ema-akhawuntini okufunda kuphela kuzofihlwa ohlwini lwakho lothintana nabo, ngeke kususwe."</string>
+ <string name="multipleContactDeleteConfirmation" msgid="938900978442960800">"Ukususa lona othintana naye kuzosusa ukwaziswa kusuka ema-akhawuntini amaningi."</string>
+ <!-- no translation found for deleteConfirmation (811706994761610640) -->
+ <skip />
+ <string name="menu_done" msgid="796017761764190697">"Kwenziwe"</string>
+ <!-- outdated translation 2174577548513895144 --> <string name="menu_doNotSave" msgid="58593876893538465">"Buyela emuva"</string>
+ <!-- no translation found for editContact_title_edit (7678695190666836093) -->
+ <skip />
+ <!-- no translation found for editContact_title_insert (9125600232291405757) -->
+ <skip />
+ <string name="label_phonetic_name" msgid="2288082649573927286">"Ifonethikhi"</string>
+ <!-- no translation found for label_notes (8337354953278341042) -->
+ <skip />
+ <string name="label_sip_address" msgid="124073911714324974">"Ikholi le-Inthanethi"</string>
+ <!-- no translation found for label_ringtone (8833166825330686244) -->
+ <skip />
+ <string name="ghostData_phonetic_name" msgid="7852749081984070902">"Igama leFonethikhi"</string>
+ <!-- no translation found for ghostData_company (5414421120553765775) -->
+ <skip />
+ <string name="ghostData_title" msgid="7496735200318496110">"Isihloko"</string>
+ <!-- no translation found for invalidContactMessage (5816991830260044593) -->
+ <skip />
+ <!-- no translation found for pickerNewContactHeader (7750705279843568147) -->
+ <skip />
+ <!-- no translation found for phoneLabelsGroup (6468091477851199285) -->
+ <skip />
+ <!-- no translation found for emailLabelsGroup (8389931313045344406) -->
+ <skip />
+ <!-- no translation found for imLabelsGroup (3898238486262614027) -->
+ <skip />
+ <!-- no translation found for postalLabelsGroup (3487738141112589324) -->
+ <skip />
+ <string-array name="otherLabels">
+ <item msgid="8287841928119937597">"Inhlangano"</item>
+ <item msgid="7196592230748086755">"Yazi"</item>
+ </string-array>
+ <!-- no translation found for photoPickerNotFoundText (6247290728908599701) -->
+ <skip />
+ <!-- no translation found for photoPickerNotFoundText (431331662154342581) -->
+ <skip />
+ <!-- no translation found for attach_photo_dialog_title (5599827035558557169) -->
+ <skip />
+ <string name="customLabelPickerTitle" msgid="1081475101983255212">"Igama lelebula efiswayo"</string>
+ <string name="menu_displayGroup" msgid="5655505437727616553">"Bonisa okukhethwa kukho"</string>
+ <string name="send_to_voicemail_checkbox" msgid="9001686764070676353">"Thumela ngokuqondile amakholi emyalezwini wezwi"</string>
+ <!-- no translation found for default_ringtone (9099988849649827972) -->
+ <skip />
+ <!-- no translation found for removePhoto (4898105274130284565) -->
+ <skip />
+ <!-- no translation found for noContacts (8579310973261953559) -->
+ <skip />
+ <!-- no translation found for noGroups (8614664663561385253) -->
+ <skip />
+ <string name="noMatchingContacts" msgid="4266283206853990471">"Abekho othintana nabo abafanayo abatholakele."</string>
+ <!-- no translation found for noContactsWithPhoneNumbers (1605457050218824269) -->
+ <skip />
+ <string name="showFilterPhones" msgid="4184858075465653970">"Kuphela othintana nabo abanamafoni"</string>
+ <string name="showFilterPhonesDescrip" msgid="6644443248815191067">"Bonisa kuphela othintana nabo abanezinombolo zocingo"</string>
+ <string name="headerContactGroups" msgid="2426134991932503843">"Khetha othintana nabo ozobabonisa"</string>
+ <plurals name="groupDescrip">
+ <item quantity="other" msgid="3507881585720628389">"<xliff:g id="COUNT">%0$d</xliff:g> othintana nabo"</item>
+ </plurals>
+ <plurals name="groupDescripPhones">
+ <item quantity="other" msgid="3816047547470490208">"<xliff:g id="COUNT_0">%1$d</xliff:g> othintana nabo, <xliff:g id="COUNTWITHPHONES">%2$d</xliff:g> abanamafoni"</item>
+ </plurals>
+ <string name="savingContact" msgid="4075751076741924939">"Igcina othintana naye..."</string>
+ <string name="savingDisplayGroups" msgid="2133152192716475939">"Igcina okukhethwa kukho kokubonisa"</string>
+ <!-- no translation found for contactSavedToast (7152589189385441091) -->
+ <skip />
+ <string name="contactSavedErrorToast" msgid="9189098776225004666">"Iphutha, ayikwazi ukugcina izinguquko zothintana naye."</string>
+ <plurals name="listTotalPhoneContacts">
+ <item quantity="one" msgid="3015357862286673986">"othintana naye ongu-1 onenombolo yocingo"</item>
+ <item quantity="other" msgid="3299954047880968205">"<xliff:g id="COUNT">%d</xliff:g> Othintana nabo abanezinombolo zocingo"</item>
+ </plurals>
+ <!-- outdated translation 2756295259674938869 --> <string name="listTotalPhoneContactsZero" msgid="6968813857632984319">"Abekho othintana nabo ababonakalayo abanezinombolo zocingo"</string>
+ <plurals name="listTotalAllContacts">
+ <item quantity="one" msgid="3405747744700823280">"Othintana naye ongu-1"</item>
+ <item quantity="other" msgid="3578469907265375314">"<xliff:g id="COUNT">%d</xliff:g> Othintana nabo"</item>
+ </plurals>
+ <!-- outdated translation 6811347506748072822 --> <string name="listTotalAllContactsZero" msgid="1889349925514589304">"Abekho othintana nabo ababonakalayo"</string>
+ <!-- no translation found for listTotalAllContactsZeroCustom (4058252141420128998) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroStarred (5391630590684099117) -->
+ <skip />
+ <!-- no translation found for listTotalAllContactsZeroGroup (5448979458248027615) -->
+ <skip />
+ <plurals name="listFoundAllContacts">
+ <item quantity="one" msgid="5517063038754171134">"kutholakele okungu-1"</item>
+ <item quantity="other" msgid="3852668542926965042">"<xliff:g id="COUNT">%d</xliff:g> tholakele"</item>
+ </plurals>
+ <string name="foundTooManyContacts" msgid="2548148047461758967">"kutholakele edlula <xliff:g id="COUNT">%d</xliff:g>"</string>
+ <string name="listFoundAllContactsZero" msgid="777952841930508289">"Akutholakali"</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one" msgid="4826918429708286628">"otholakele ongu-1"</item>
+ <item quantity="other" msgid="7988132539476575389">"<xliff:g id="COUNT">%d</xliff:g> tholakele"</item>
+ </plurals>
+ <!-- no translation found for contactsIconLabel (7666609097606552806) -->
+ <skip />
+ <!-- no translation found for contactsGroupsLabel (2841971472518003524) -->
+ <skip />
+ <!-- no translation found for contactsFavoritesLabel (8417039765586853670) -->
+ <skip />
+ <string name="dialerIconLabel" msgid="6500826552823403796">"Ifoni"</string>
+ <!-- no translation found for recentCallsIconLabel (1419116422359067949) -->
+ <skip />
+ <string name="liveFolderAll" msgid="4789010460767506206">"Bonke othintana nabo"</string>
+ <string name="liveFolderFavorites" msgid="3100957542927222282">"Othintana nabo abanezinkanyezi"</string>
+ <string name="liveFolderPhone" msgid="3739376066610926780">"Othintana nabo abanezinombolo zocingo"</string>
+ <string name="menu_sendTextMessage" msgid="6937343460284499306">"Thumela umyalezo wombhalo"</string>
+ <string name="recentCalls_callNumber" msgid="1756372533999226126">"Shayela <xliff:g id="NAME">%s</xliff:g>"</string>
+ <!-- no translation found for recentCalls_editNumberBeforeCall (7756171675833267857) -->
+ <skip />
+ <!-- no translation found for recentCalls_addToContact (1429899535546487008) -->
+ <skip />
+ <!-- no translation found for recentCalls_removeFromRecentList (401662244636511330) -->
+ <skip />
+ <!-- no translation found for recentCalls_deleteAll (6352364392762163704) -->
+ <skip />
+ <!-- no translation found for recentCalls_empty (247053222448663107) -->
+ <skip />
+ <string name="clearCallLogConfirmation_title" msgid="718072843006222703">"Sula ifayela lokungena"</string>
+ <string name="clearCallLogConfirmation" msgid="7625927669136267636">"Uqinisekile ukuthi ufuna ukusula ifayela lokungena?"</string>
+ <!-- no translation found for clearCallLogProgress_title (6870412675015656948) -->
+ <skip />
+ <!-- no translation found for imei (3045126336951684285) -->
+ <skip />
+ <string name="meid" msgid="6210568493746275750">"I-MEID"</string>
+ <!-- no translation found for voicemail (3851469869202611441) -->
+ <skip />
+ <!-- no translation found for unknown (740067747858270469) -->
+ <skip />
+ <!-- no translation found for private_num (6374339738119166953) -->
+ <skip />
+ <string name="payphone" msgid="4864313342828942922">"Ifoni ekhokhelwayo"</string>
+ <!-- no translation found for dialerKeyboardHintText (5401660096579787344) -->
+ <skip />
+ <string name="dialerDialpadHintText" msgid="5824490365898349041">"Dayela ukwengeza ikholi"</string>
+ <!-- no translation found for simContacts_emptyLoading (6700035985448642408) -->
+ <skip />
+ <!-- no translation found for simContacts_title (27341688347689769) -->
+ <skip />
+ <string name="noContactsHelpTextWithSyncForCreateShortcut" msgid="801504710275614594">"Awunabo othintana nabo ongababonisa. (Uma usanda kufaka i-akhawunti, kungase kuthathe imizuzu embalwa ukuvumelanisa othintana nabo.)"</string>
+ <string name="noContactsHelpTextForCreateShortcut" msgid="3081286388667108335">"Awunabo othintana nabo ongababonisa."</string>
+ <!-- outdated translation 7633826236417884130 --> <string name="noContactsHelpText" product="tablet" msgid="6450346791169710787">"Awunabo othintana nabo ongababonisa."\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"ama-Akhawunti"</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n" "</li>" "\n<li>" "<font fgcolor="#ffffffff">" "<b>"Othintana naye omusha "</b>" "</font>" ukwenza othintana naye omusha kusuka ekuqaleni"\n" "</li>" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kwi-SIM yakho noma ikhadi le-SD"\n</li></string>
+ <string name="noContactsHelpText" product="default" msgid="7633826236417884130">"Awunabo othintana nabo ongababonisa."\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"ama-Akhawunti"</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n" "</li>" "\n<li>" "<font fgcolor="#ffffffff">" "<b>"Othintana naye omusha "</b>" "</font>" ukwenza othintana naye omusha kusuka ekuqaleni"\n" "</li>" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kwi-SIM yakho noma ikhadi le-SD"\n</li></string>
+ <!-- outdated translation 3017521127042216243 --> <string name="noContactsHelpTextWithSync" product="tablet" msgid="2364665535969139880">"Awunabo othintana nabo ongababonisa. (Uma usanda kufaka i-akhawunti, kungase kuthathe imizuzu embalwa ukuvumelanisa othintana nabo.)"\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti"</b></font>" ukufaka noma ukuvumelanisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Bonisa okukhethwa kukho"</b></font>" ukushintsha ukuthi yibaphi othintana nabo abaonakalayo"\n" "</li>" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"Othintana naye omusha"</b></font>" ukwenza othintana naye omusha kusuka ekuqaleni"\n</li>\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kwi-SIM yakho noma ikhadi le-SD"\n</li></string>
+ <string name="noContactsHelpTextWithSync" product="default" msgid="3017521127042216243">"Awunabo othintana nabo ongababonisa. (Uma usanda kufaka i-akhawunti, kungase kuthathe imizuzu embalwa ukuvumelanisa othintana nabo.)"\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti"</b></font>" ukufaka noma ukuvumelanisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Bonisa okukhethwa kukho"</b></font>" ukushintsha ukuthi yibaphi othintana nabo abaonakalayo"\n" "</li>" "\n" "<li>" "<font fgcolor="#ffffffff">" "<b>"Othintana naye omusha"</b></font>" ukwenza othintana naye omusha kusuka ekuqaleni"\n</li>\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kwi-SIM yakho noma ikhadi le-SD"\n</li></string>
+ <!-- outdated translation 467658807711582876 --> <string name="noContactsNoSimHelpText" product="tablet" msgid="6031363021287849874">"Awunabo othintana nabo ongababonisa."\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta: "\n" "\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti "</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ongabavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Othintana naye omusha"</b></font>" ukwenza othintana naye kusuka ekuqaleni"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>"ukungenisa othintana nabo kusuka ekhadini lakho le-SD"\n</li></string>
+ <string name="noContactsNoSimHelpText" product="default" msgid="467658807711582876">"Awunabo othintana nabo ongababonisa."\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta: "\n" "\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti "</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ongabavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Othintana naye omusha"</b></font>" ukwenza othintana naye kusuka ekuqaleni"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>"ukungenisa othintana nabo kusuka ekhadini lakho le-SD"\n</li></string>
+ <!-- outdated translation 9040060730467973050 --> <string name="noContactsNoSimHelpTextWithSync" product="tablet" msgid="6222739731808897565">"Awunabo othintana nabo ongababonisa. (Uma usanda kufaka i-akhawunti, kungase kuthathe imizuzu embalwa ukuvumelanisa othintana nabo.)"\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti"</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Bonisa okukhethwa kukho"</b></font>" ukushintsha ukuthi yibaphi othintana nabo ababonakalayo"\n</li>\n<li><font fgcolor="#ffffffff"><b>"Othintana naye omusha"</b></font>" ukwenza othintana naye omusha kusuka ekuqaleni "\n</li>\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kusuka ekhadini lakho le-SD"\n</li></string>
+ <string name="noContactsNoSimHelpTextWithSync" product="default" msgid="9040060730467973050">"Awunabo othintana nabo ongababonisa. (Uma usanda kufaka i-akhawunti, kungase kuthathe imizuzu embalwa ukuvumelanisa othintana nabo.)"\n\n"Ukufaka othintana nabo, cindezela "<font fgcolor="#ffffffff"><b>"Menyu"</b></font>" bese uthinta:"\n\n<li><font fgcolor="#ffffffff"><b>"ama-Akhawunti"</b></font>" ukufaka noma ukumisa i-akhawunti nothintana nabo ungavumelanisa efonini"\n</li>" "\n<li><font fgcolor="#ffffffff"><b>"Bonisa okukhethwa kukho"</b></font>" ukushintsha ukuthi yibaphi othintana nabo ababonakalayo"\n</li>\n<li><font fgcolor="#ffffffff"><b>"Othintana naye omusha"</b></font>" ukwenza othintana naye omusha kusuka ekuqaleni "\n</li>\n<li><font fgcolor="#ffffffff"><b>"Ngenisa/Thekelisa"</b></font>" ukungenisa othintana nabo kusuka ekhadini lakho le-SD"\n</li></string>
+ <string name="noFavoritesHelpText" msgid="3744655776704833277">"Awunazo izintandokazi."\n\n"Ukufaka othintana naye ohlwini lwakho lwezintandokazi:"\n\n" "<li>"Thinta "<b>"ithebhu"</b>" Yothintana nabo"\n</li>" "\n<li>"Thinta othintana naye ofuna ukumufaka ezintandokazini zakho"\n</li>" "\n<li>"Thinta inkanyezi eseduze negama lothintana naye"\n</li></string>
+ <string name="liveFolder_all_label" msgid="5961411940473276616">"Bonke othintana nabo"</string>
+ <string name="liveFolder_favorites_label" msgid="2674341514070517105">"Okunenkanyezi"</string>
+ <string name="liveFolder_phones_label" msgid="1709786878793436245">"Amafoni"</string>
+ <string name="dialer_useDtmfDialpad" msgid="1707548397435075040">"Sebenzisa ikhiphedi yethoni yokuthinta"</string>
+ <string name="dialer_returnToInCallScreen" msgid="3719386377550913067">"Buyela kukholi eqhubekayo"</string>
+ <string name="dialer_addAnotherCall" msgid="4205688819890074468">"Yengeza ikholi"</string>
+ <string name="callDetailTitle" msgid="5340227785196217938">"Imininingwane yokushayela"</string>
+ <string name="toast_call_detail_error" msgid="7200975244804730096">"Ayikwazanga ukufunda imininingwane yokushayela okuceliwe."</string>
+ <string name="type_incoming" msgid="6502076603836088532">"Ikholi engenayo"</string>
+ <string name="type_outgoing" msgid="343108709599392641">"Ikholi oluphumayo"</string>
+ <string name="type_missed" msgid="2720502601640509542">"Ikholi elahlekeli"</string>
+ <string name="actionIncomingCall" msgid="6028930669817038600">"Amakholi angenayo"</string>
+ <string name="callBack" msgid="5498224409038809224">"Phinda ushayele"</string>
+ <string name="callAgain" msgid="3197312117049874778">"Shayela futhi"</string>
+ <string name="returnCall" msgid="8171961914203617813">"Buyisela ikholi"</string>
+ <string name="callDetailsDurationFormat" msgid="8157706382818184268">"<xliff:g id="MINUTES">%s</xliff:g> amaminithi <xliff:g id="SECONDS">%s</xliff:g> amasekhondi"</string>
+ <string name="favoritesFrquentSeparator" msgid="8107518433381283736">"Abathintwa njalo"</string>
+ <string name="add_contact_dlg_title" msgid="2896685845822146494">"Faka othintana naye"</string>
+ <string name="add_contact_dlg_message_fmt" msgid="7986472669444326576">"Faka \"<xliff:g id="EMAIL">%s</xliff:g>\" kothintana nabo?"</string>
+ <string name="description_image_button_one" msgid="1740638037139856139">"kunye"</string>
+ <string name="description_image_button_two" msgid="5882638439003731308">"okubili"</string>
+ <string name="description_image_button_three" msgid="8709731759376015180">"ntathu"</string>
+ <string name="description_image_button_four" msgid="3530239685642246130">"okune"</string>
+ <string name="description_image_button_five" msgid="1182465427501188413">"okuhlanu"</string>
+ <string name="description_image_button_six" msgid="2093656269261415475">"isithupha"</string>
+ <string name="description_image_button_seven" msgid="2450357020447676481">"isikhombisa"</string>
+ <string name="description_image_button_eight" msgid="6969435115163287801">"isishiyagalombili"</string>
+ <string name="description_image_button_nine" msgid="7857248695662558323">"isishiyagalolunye"</string>
+ <string name="description_image_button_star" msgid="3365919907520767866">"ikanyezi"</string>
+ <string name="description_image_button_zero" msgid="4133108949401820710">"lutho"</string>
+ <string name="description_image_button_pound" msgid="3039765597595889230">"iphawundi"</string>
+ <string name="description_voicemail_button" msgid="3402506823655455591">"Umyalezo wezwi"</string>
+ <string name="description_dial_button" msgid="1274091017188142646">"dayela"</string>
+ <string name="description_delete_button" msgid="6263102114033407382">"i-backspace"</string>
+ <string name="description_digits_edittext" msgid="8760207516497016437">"inombolo okumele uyidayele"</string>
+ <string name="description_contact_photo" msgid="3387458082667894062">"isithombe sothintana naye"</string>
+ <string name="description_minus_button" msgid="387136707700230172">"susa"</string>
+ <string name="description_plus_button" msgid="515164827856229880">"kuhlanganise"</string>
+ <!-- outdated translation 5911758680339949273 --> <string name="no_sdcard_title" product="nosdcard" msgid="8543619259870877473">"Alikho ikhadi le-SD"</string>
+ <string name="no_sdcard_title" product="default" msgid="5911758680339949273">"Alikho ikhadi le-SD"</string>
+ <!-- outdated translation 6019391476490445358 --> <string name="no_sdcard_message" product="nosdcard" msgid="1334170151822669976">"Alikho ikhadi le-SD"</string>
+ <string name="no_sdcard_message" product="default" msgid="6019391476490445358">"Alikho ikhadi le-SD"</string>
+ <string name="searching_vcard_title" msgid="4970508055399376813">"Iseshela i-vCArd"</string>
+ <string name="import_from_sim" msgid="3859272228033941659">"Ngenisa kusuka kwikhadi le-SIM"</string>
+ <!-- outdated translation 8550360976693202816 --> <string name="import_from_sdcard" product="nosdcard" msgid="8668347930577565175">"Ngenisa kusuka ekhadini le-SD"</string>
+ <string name="import_from_sdcard" product="default" msgid="8550360976693202816">"Ngenisa kusuka ekhadini le-SD"</string>
+ <!-- outdated translation 2597105442616166277 --> <string name="export_to_sdcard" product="nosdcard" msgid="6092815580965201089">"Thekelisa ekhadini le-SD"</string>
+ <string name="export_to_sdcard" product="default" msgid="2597105442616166277">"Thekelisa ekhadini le-SD"</string>
+ <string name="share_visible_contacts" msgid="890150378880783797">"Yabelana nothintana nabo ababonakalayo"</string>
+ <string name="import_one_vcard_string" msgid="9059163467020328433">"Ngenisa ifayela eyodwa ye-vCard"</string>
+ <string name="import_multiple_vcard_string" msgid="3810226492811062392">"Ngenisa amafayela amaningi e-vCard"</string>
+ <string name="import_all_vcard_string" msgid="5518136113853448474">"Ngenisa wonke amafayela e-vCard"</string>
+ <!-- outdated translation 6917522333561434546 --> <string name="searching_vcard_message" product="nosdcard" msgid="996170203695743981">"Iseshela idatha ye-vCard ekhadini le-SD"</string>
+ <string name="searching_vcard_message" product="default" msgid="6917522333561434546">"Iseshela idatha ye-vCard ekhadini le-SD"</string>
+ <!-- outdated translation 3506782007953167180 --> <string name="scanning_sdcard_failed_title" product="nosdcard" msgid="6957414493948497249">"Ukuthwebula ikhadi le-SD kwehlulekile"</string>
+ <string name="scanning_sdcard_failed_title" product="default" msgid="3506782007953167180">"Ukuthwebula ikhadi le-SD kwehlulekile"</string>
+ <!-- no translation found for scanning_sdcard_failed_message (4106156155205860626) -->
+ <skip />
+ <string name="scanning_sdcard_failed_message" product="default" msgid="3761992500690182922">"Ukuthwebula ikhadi le-SD kwehlulekile (Isizathu: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_io_error" msgid="5922864781066136340">"I/O Iphutha"</string>
+ <string name="fail_reason_low_memory_during_import" msgid="7514918659342886381">"Inkumbulo ayanele (kungenzeka ifayela inkulu kakhulu)"</string>
+ <string name="fail_reason_vcard_parse_error" msgid="1201233722762680214">"Yehlulekile ukunqunta i-vCard ngokwesizathu esingalindelekile"</string>
+ <!-- no translation found for fail_reason_not_supported (294499264620201243) -->
+ <skip />
+ <!-- no translation found for vcard_import_failed (7718330063493653085) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (6339234836196984924) -->
+ <skip />
+ <!-- no translation found for import_failure_no_vcard_file (1730986357514922756) -->
+ <skip />
+ <string name="fail_reason_failed_to_collect_vcard_meta_info" msgid="4154492282316067754">"Yehlulekile ukuqoqa ulwazi lweemetha kwefayela(ama) enikeziwe ye-vCard."</string>
+ <string name="fail_reason_failed_to_read_files" msgid="3659521123567134029">"Eyodwa noma eyengeziwe yamafayela yehlulekile ukungenisa (%s)."</string>
+ <string name="fail_reason_unknown" msgid="999034019513096768">"Iphutha elingaziwa"</string>
+ <string name="select_vcard_title" msgid="3968948173786172468">"Khetha ifayela ye-vCard"</string>
+ <string name="caching_vcard_title" msgid="5009556022082659780">"Ilondoloza okwesikhashana i-vCard(ama) ekulondolozeni kwesikhashana kwasendaweni"</string>
+ <string name="caching_vcard_message" msgid="2380844718093378900">"Umngenisi ulondoloza okwesikhashana i-vCard(ama) ekulondolozeni kwesikhashana kwasendaweni. Ukungenisa kwangempela kuzoqala maduze."</string>
+ <string name="progress_notifier_message" msgid="2311011466908220528">"Ingenisa <xliff:g id="CURRENT_NUMBER">%s</xliff:g>/<xliff:g id="TOTAL_NUMBER">%s</xliff:g>: <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="importing_vcard_description" msgid="4245275224298571351">"Iyangenisa <xliff:g id="NAME">%s</xliff:g>"</string>
+ <string name="reading_vcard_failed_title" msgid="2162610359561887043">"Yehlulekile Ukufunda idatha ye-vCard"</string>
+ <string name="reading_vcard_canceled_title" msgid="1770608329958463131">"Ukufunda idatha ye-vCard kukhanseliwe"</string>
+ <!-- no translation found for importing_vcard_finished_title (3341541727268747967) -->
+ <skip />
+ <!-- no translation found for importing_vcard_canceled_title (6367906965439777280) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message (2804911199145873396) -->
+ <skip />
+ <!-- no translation found for vcard_import_will_start_message_with_default_name (1022969530654129470) -->
+ <skip />
+ <!-- no translation found for vcard_import_request_rejected_message (2592424820635325951) -->
+ <skip />
+ <!-- no translation found for vcard_export_will_start_message (2210241345252081463) -->
+ <skip />
+ <!-- no translation found for vcard_export_request_rejected_message (8259494002258326330) -->
+ <skip />
+ <!-- no translation found for vcard_unknown_filename (7171709890959915954) -->
+ <skip />
+ <string name="percentage" msgid="34897865327092209">"%S%%"</string>
+ <string name="confirm_export_title" msgid="7648747763127442983">"Qinisekisa ukuthunyelwa kwenye indawo"</string>
+ <string name="confirm_export_message" msgid="3875683519257829750">"Uqinisekile ukuba ufuna ukuthekelisa uhlu lwakho lothintana naye ku \"<xliff:g id="VCARD_FILENAME">%s</xliff:g>\""</string>
+ <string name="exporting_contact_failed_title" msgid="585823094820602526">"Yehlulekile ukuthekelisa idatha yothintana naye"</string>
+ <string name="exporting_contact_failed_message" msgid="4151348002470298092">"Yehlulekile ukuthekelisa idatha yothintana naye. "\n"Isizathu sokwehluleka: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_no_exportable_contact" msgid="4919714086648344495">"Akekho othintana naye othelekisekayo"</string>
+ <!-- outdated translation 7084146295639672658 --> <string name="fail_reason_too_many_vcard" product="nosdcard" msgid="3745507837635270265">"Kunamafayela aminingi kakhulu e-vCard kwikhadi le-SD"</string>
+ <string name="fail_reason_too_many_vcard" product="default" msgid="7084146295639672658">"Kunamafayela aminingi kakhulu e-vCard kwikhadi le-SD"</string>
+ <string name="fail_reason_too_long_filename" msgid="1915716071321839166">"Igama lefayela elidingekayo lide kakhulu (\" <xliff:g id="FILENAME">%s</xliff:g>\")"</string>
+ <!-- no translation found for exporting_vcard_finished_title (4259736138838583213) -->
+ <skip />
+ <!-- no translation found for exporting_vcard_canceled_title (1827672399438062140) -->
+ <skip />
+ <string name="exporting_contact_list_title" msgid="9072240631534457415">"Ithekelisa idatha yothintana naye"</string>
+ <string name="exporting_contact_list_message" msgid="5640326540405486055">"Ithekelisa idatha yothintana naye ku \"<xliff:g id="FILE_NAME">%s</xliff:g>\""</string>
+ <string name="fail_reason_could_not_initialize_exporter" msgid="4943708332700987376">"Ayikwazanga ukuqalisa isithekelisi: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="fail_reason_error_occurred_during_export" msgid="2151165129433831202">"Iphutha livele phakathi nokuthekelisa: \"<xliff:g id="EXACT_REASON">%s</xliff:g>\""</string>
+ <string name="composer_failed_to_get_database_infomation" msgid="3723109558155169053">"Yehlulekile ukuthola ukwaziswa kwemininingo egciniwe"</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="tablet" msgid="5161491059051198932">"Akekho othintana naye othekelisekayo. Uma unothintana nabo efonini yakho, bonke othintana nabo bangavimbelwa ukuthekeliswa ngaphandle kwefoni omunye umhlinzeki wedatha."</string>
+ <!-- outdated translation 754734132189369094 --> <string name="composer_has_no_exportable_contact" product="default" msgid="322344221706924358">"Akekho othintana naye othekelisekayo. Uma unothintana nabo efonini yakho, bonke othintana nabo bangavimbelwa ukuthekeliswa ngaphandle kwefoni omunye umhlinzeki wedatha."</string>
+ <string name="composer_not_initialized" msgid="8041534450748388843">"Isiqambi se-vCard asiqalisiwe kahle"</string>
+ <string name="fail_reason_could_not_open_file" msgid="4013520943128739511">"Ayikwazi ukuvula \"<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> kothintana nabo abangu-<xliff:g id="TOTAL_NUMBER">%s</xliff:g>"</string>
+ <!-- no translation found for cancel_import_confirmation_title (5578683596010294836) -->
+ <skip />
+ <!-- no translation found for cancel_import_confirmation_message (8560937090143057107) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_title (6516467140276768528) -->
+ <skip />
+ <!-- no translation found for cancel_export_confirmation_message (1392976902396351957) -->
+ <skip />
+ <!-- no translation found for cancel_vcard_import_or_export_failed (7096533244663846810) -->
+ <skip />
+ <string name="search_settings_description" msgid="2675223022992445813">"Amagama othintana nabo"</string>
+ <string name="add_2sec_pause" msgid="9214012315201040129">"Faka ukumisa okwesikhashana kwamasekhondi angu-2"</string>
+ <string name="add_wait" msgid="3360818652790319634">"Yengeza ukulinda"</string>
+ <string name="call_disambig_title" msgid="1911302597959335178">"Shayela usebenzisa"</string>
+ <string name="sms_disambig_title" msgid="4675399294513152364">"Bhalela usebenzisa"</string>
+ <string name="make_primary" msgid="5829291915305113983">"Khumbula lokhu okukhethiwe"</string>
+ <string name="quickcontact_missing_app" msgid="4600366393134289038">"Alukho uhlobo lokusebenza olutholakele lokuphatha lesenzo"</string>
+ <string name="quickcontact_remember_choice" msgid="5964536411579749424">"Khumbula lokhu okukhethiwe"</string>
+ <string name="quickcontact_missing_name" msgid="5590266114306996632">"Akwaziwa"</string>
+ <string name="quickcontact_no_data" msgid="2098000859125253675">"Ayikho idatha"</string>
+ <!-- no translation found for quickcontact_clear_defaults_description (3792792870662989100) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_caption (4287306111861545753) -->
+ <skip />
+ <!-- no translation found for quickcontact_clear_defaults_button (8728754360205289059) -->
+ <skip />
+ <string name="menu_accounts" msgid="8499114602017077970">"Ama-akhawunti"</string>
+ <string name="menu_import_export" msgid="3765725645491577190">"Ngenisa/Thekelisa"</string>
+ <string name="dialog_import_export" msgid="4771877268244096596">"Ngenisa/Thekelisa othintana nabo"</string>
+ <!-- outdated translation 943789700636542260 --> <string name="menu_share" msgid="8746849630474240344">"Yabelana"</string>
+ <string name="share_via" msgid="563121028023030093">"Abelana nothintana naye nge"</string>
+ <string name="share_error" msgid="4374508848981697170">"Lona othintana naye akakwazi ukwabelana."</string>
+ <string name="nameLabelsGroup" msgid="2034640839640477827">"Igama"</string>
+ <string name="nicknameLabelsGroup" msgid="2891682101053358010">"Igama lokudlala"</string>
+ <string name="organizationLabelsGroup" msgid="2478611760751832035">"Inhlangano"</string>
+ <string name="websiteLabelsGroup" msgid="4202998982804009261">"Iwebhusayithi"</string>
+ <string name="eventLabelsGroup" msgid="8069912895912714412">"Isenzakalo"</string>
+ <!-- no translation found for relationLabelsGroup (1854373894284572781) -->
+ <skip />
+ <string name="groupsLabel" msgid="8573535366319059326">"Amaqembu"</string>
+ <string name="type_short_home" msgid="7770424864090605384">"H"</string>
+ <string name="type_short_mobile" msgid="1655473281466676216">"M"</string>
+ <string name="type_short_work" msgid="4925330752504537861">"W"</string>
+ <string name="type_short_pager" msgid="2613818970827594238">"P"</string>
+ <string name="type_short_other" msgid="5669407180177236769">"O"</string>
+ <string name="dialog_new_contact_account" msgid="9044704073286262197">"Yenza othintana naye ngaphansi kwe-akhawunti"</string>
+ <string name="menu_sync_remove" msgid="3266725887008450161">"Khipha iqembu lokuvumelanisa"</string>
+ <string name="dialog_sync_add" msgid="8267045393119375803">"Ngeza iqembu lokuvumelanisa"</string>
+ <string name="display_more_groups" msgid="2682547080423434170">"Amanye amaqembu..."</string>
+ <string name="display_ungrouped" msgid="4602580795576261158">"Bonke Abanye Othintana Nabo"</string>
+ <string name="display_all_contacts" msgid="6846131371214707956">"Bonke Othintana Nabo"</string>
+ <string name="display_warn_remove_ungrouped" msgid="2314043155909167610">" Ukukhipha \'<xliff:g id="GROUP">%s</xliff:g> ekuvumalesaneni kuzokhipha futhi noma yibaphi othintana nabo abangaqoqiwe ekuvumelasaneni."</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="tablet" msgid="7946049152658522054">"Ifoni kuphela (akuvumelanisiwe)"</string>
+ <!-- outdated translation 4025734638492419713 --> <string name="account_phone" product="default" msgid="3682950835276226870">"Ifoni kuphela (akuvumelanisiwe)"</string>
+ <string name="call_custom" msgid="7756571794763171802">"Shayela <xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="call_home" msgid="1990519474420545392">"Shayela ekhaya"</string>
+ <string name="call_mobile" msgid="7502236805487609178">"Shayela ifoni"</string>
+ <string name="call_work" msgid="5328785911463744028">"Shayela emsebenzini"</string>
+ <string name="call_fax_work" msgid="7467763592359059243">"Shayela ifeksi yasemsebenzini"</string>
+ <string name="call_fax_home" msgid="8342175628887571876">"Shayela ifeksi yasekhaya"</string>
+ <string name="call_pager" msgid="9003902812293983281">"Shayela isicingo"</string>
+ <string name="call_other" msgid="8563753966926932052">"Shayela"</string>
+ <string name="call_callback" msgid="1910165691349426858">"Shayela ukuphinda ushaye"</string>
+ <string name="call_car" msgid="3280537320306436445">"Shayela imoto"</string>
+ <string name="call_company_main" msgid="6105120947138711257">"Shayela isisekelo senkampani"</string>
+ <string name="call_isdn" msgid="1541590690193403411">"Shayela i-ISDN"</string>
+ <string name="call_main" msgid="6082900571803441339">"Shayela isisekelo"</string>
+ <string name="call_other_fax" msgid="5745314124619636674">"Shayela ifeksi"</string>
+ <string name="call_radio" msgid="8296755876398357063">"Shayela umsakazo"</string>
+ <string name="call_telex" msgid="2223170774548648114">"Shayela i-telex"</string>
+ <string name="call_tty_tdd" msgid="8951266948204379604">"Shayela i-TTY/TDD"</string>
+ <string name="call_work_mobile" msgid="8707874281430105394">"Shayela ifoni yasemsebenzini"</string>
+ <string name="call_work_pager" msgid="3419348514157949008">"Shayela isicingo sasemsebenzini"</string>
+ <string name="call_assistant" msgid="2141641383068514308">"Shayela<xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="call_mms" msgid="6274041545876221437">"Shayela i-MMS"</string>
+ <string name="sms_custom" msgid="5932736853732191825">" Okubhaliwe<xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="sms_home" msgid="7524332261493162995">"Ikhaya lombhalo"</string>
+ <string name="sms_mobile" msgid="5200107250451030769">"Umbhalo wefoni"</string>
+ <string name="sms_work" msgid="2269624156655267740">"Bhalela emsebenzini"</string>
+ <string name="sms_fax_work" msgid="8028189067816907075">"Bhalela ifeksi yasemsebenzini"</string>
+ <string name="sms_fax_home" msgid="9204042076306809634">"Bhalela ifeksi yasekhaya"</string>
+ <string name="sms_pager" msgid="7730404569637015192">"Bhalela isicingo"</string>
+ <string name="sms_other" msgid="806127844607642331">"Umbhalo"</string>
+ <string name="sms_callback" msgid="5004824430094288752">"Bhalela ukuphinda ukushayela"</string>
+ <string name="sms_car" msgid="7444227058437359641">"Bhalela imoto"</string>
+ <string name="sms_company_main" msgid="118970873419678087">"Bhalela isisekelo senkampani"</string>
+ <string name="sms_isdn" msgid="8153785037515047845">"Bhalela i-ISDN"</string>
+ <string name="sms_main" msgid="8621625784504541679">"Bhalela isisekelo"</string>
+ <string name="sms_other_fax" msgid="3888842199855843152">"Ifeksi yombhalo"</string>
+ <string name="sms_radio" msgid="3329166673433967820">"Bhalela umsakazo"</string>
+ <string name="sms_telex" msgid="9034802430065267848">"Bhalela i-telex"</string>
+ <string name="sms_tty_tdd" msgid="6782284969132531532">"Bhalela i-TTY/TDD"</string>
+ <string name="sms_work_mobile" msgid="2459939960512702560">"Bhalela ifoni yasemsebenzini"</string>
+ <string name="sms_work_pager" msgid="5566924423316960597">"Bhalela isicingo sasemsebenzini"</string>
+ <string name="sms_assistant" msgid="2773424339923116234">"Okubhaliwe<xliff:g id="ASSISTANT">%s</xliff:g>"</string>
+ <string name="sms_mms" msgid="4069352461380762677">"Bhala i-MMS"</string>
+ <string name="email_home" msgid="8573740658148184279">"Ikhaya le-imeyili"</string>
+ <string name="email_mobile" msgid="2042889209787989814">"Imeyla ifoni"</string>
+ <string name="email_work" msgid="2807430017302722689">"Imeyila emsebenzini"</string>
+ <string name="email_other" msgid="3454004077967657109">"I-imeyli"</string>
+ <string name="email_custom" msgid="7548003991586214105">"I-imeyili<xliff:g id="CUSTOM">%s</xliff:g>"</string>
+ <string name="email" msgid="5668400997660065897">"I-imeyili"</string>
+ <string name="map_home" msgid="1243547733423343982">"Vuka ikheli lasekhaya"</string>
+ <string name="map_work" msgid="1360474076921878088">"Buka ikheli lasemsebenzini"</string>
+ <string name="map_other" msgid="3817820803587012641">"Buka ikheli"</string>
+ <string name="map_custom" msgid="6184363799976265281">"Buka <xliff:g id="CUSTOM">%s</xliff:g> ikheli"</string>
+ <string name="chat_aim" msgid="2588492205291249142">"Xoxa usebenzisa i-AIM"</string>
+ <string name="chat_msn" msgid="8041633440091073484">"Xoxa usebenzisa i-Windows Live"</string>
+ <string name="chat_yahoo" msgid="6629211142719943666">"Xoxa usebenzisa i-Yahoo"</string>
+ <string name="chat_skype" msgid="1210045020427480566">"Xoxa usebenzisa i-Skype"</string>
+ <string name="chat_qq" msgid="4294637812847719693">"Xoxa usebenzisa i-QQ"</string>
+ <string name="chat_gtalk" msgid="981575737258117697">"Xoxa usebenzisa i-Google Talk"</string>
+ <string name="chat_icq" msgid="8438405386153745775">"Xoxa usebenzisa i-ICQ"</string>
+ <string name="chat_jabber" msgid="7561444230307829609">"Xoxa usebenzisa i-Jabber"</string>
+ <string name="chat" msgid="9025361898797412245">"Xoxa"</string>
+ <string name="postal_address" msgid="8765560217149624536">"Ikheli"</string>
+ <string name="postal_street" msgid="8133143961580058972">"Isitaladi"</string>
+ <string name="postal_pobox" msgid="4431938829180269821">"PO box"</string>
+ <string name="postal_neighborhood" msgid="1450783874558956739">"Indawo yasekhaya"</string>
+ <string name="postal_city" msgid="6597491300084895548">"Idolobha"</string>
+ <string name="postal_region" msgid="6045263193478437672">"Idolobha"</string>
+ <string name="postal_postcode" msgid="572136414136673751">"Ikhodi ye-ZIP"</string>
+ <string name="postal_country" msgid="7638264508416368690">"Izwe"</string>
+ <string name="full_name" msgid="6602579550613988977">"Igama"</string>
+ <string name="name_given" msgid="1687286314106019813">"Igama elinikeziwe"</string>
+ <string name="name_family" msgid="3416695586119999058">"Igama lomkhaya"</string>
+ <string name="name_prefix" msgid="59756378548779822">"Qamba isiqalo"</string>
+ <string name="name_middle" msgid="8467433655992690326">"Igama"</string>
+ <string name="name_suffix" msgid="3855278445375651441">"Qamba isijobelelo"</string>
+ <string name="name_phonetic_given" msgid="6853570431394449191">"Igama elinikeziwe lefonethikhi"</string>
+ <string name="name_phonetic_middle" msgid="8643721493320405200">"Igama lefonethikhi"</string>
+ <string name="name_phonetic_family" msgid="462095502140180305">"Igama lomkhaya wefonethikhi"</string>
+ <!-- no translation found for name_phonetic (4259595234312430484) -->
+ <skip />
+ <string name="account_type_format" msgid="718948015590343010">"Othintana naye nge-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <!-- no translation found for from_account_format (4469138575127580203) -->
+ <skip />
+ <string name="use_photo_as_primary" msgid="8807110122951157246">"Sebenzisa lesi sithombe"</string>
+ <string name="contact_read_only" msgid="1203216914575723978">"<xliff:g id="SOURCE">%1$s</xliff:g> imininingwane yothintana naye akuhleleki kule divayisi."</string>
+ <string name="no_contact_details" msgid="6754415338321837001">"Alukho ulwazi olwengeziwe lwalona othintana naye"</string>
+ <string name="display_options_sort_list_by" msgid="6080091755852211076">"Hlunga uhlu nge"</string>
+ <string name="display_options_sort_by_given_name" msgid="184916793466387067">"Igama elinikeziwe"</string>
+ <string name="display_options_sort_by_family_name" msgid="7857986975275712622">"Igama lomkhaya"</string>
+ <string name="display_options_view_names_as" msgid="18022868169627979">"Buka amagama othintana nabo njenge"</string>
+ <string name="display_options_view_given_name_first" msgid="6968288511197363292">"Igama elinikeziwe kuqala"</string>
+ <string name="display_options_view_family_name_first" msgid="1447288164951453714">"Igama lomkhaya kuqala"</string>
+ <string name="search_bar_hint" msgid="1012756309632856553">"Sesha othintana nabo"</string>
+ <string name="search_for_all_contacts" msgid="6644963335787294131">"Sesha bonke othintana nabo"</string>
+ <string name="take_photo" msgid="7496128293167402354">"Thatha isithombe"</string>
+ <!-- no translation found for take_new_photo (7341354729436576304) -->
+ <skip />
+ <string name="pick_photo" msgid="448886509158039462">"Khetha isithombe kwiGalari"</string>
+ <!-- no translation found for pick_new_photo (7962368009197147617) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in locale_change_in_progress -->
+ <skip />
+ <!-- no translation found for locale_change_in_progress (7583992153091537467) -->
+ <skip />
+ <!-- unknown placeholder BREAK_0 in upgrade_in_progress -->
+ <skip />
+ <!-- no translation found for upgrade_in_progress (474511436863451061) -->
+ <skip />
+ <!-- no translation found for upgrade_out_of_memory (6153384328042175667) -->
+ <skip />
+ <string name="upgrade_out_of_memory_uninstall" msgid="1721798828992091432">"Khipa ezinye izinhlelo zokusebenza"</string>
+ <string name="upgrade_out_of_memory_retry" msgid="8431289830472724609">"Zama futhi ukuthuthukisa"</string>
+ <string name="search_results_searching" msgid="7755623475227227314">"Iyasesha..."</string>
+ <string name="menu_display_selected" msgid="6470001164297969034">"Khetha okukhethiwe"</string>
+ <string name="menu_display_all" msgid="8887488642609786198">"Bonisa konke"</string>
+ <string name="menu_select_all" msgid="621719255150713545">"Khetha konke"</string>
+ <string name="menu_select_none" msgid="7093222469852132345">"Ungakhethi konke"</string>
+ <plurals name="multiple_picker_title">
+ <item quantity="one" msgid="4761009734586319101">"umamukeli ongu-1 okhethiwe"</item>
+ <item quantity="other" msgid="4608837420986126229">"<xliff:g id="COUNT">%d</xliff:g> abamukeli abakhethiwe"</item>
+ </plurals>
+ <string name="no_contacts_selected" msgid="5877803471037324613">"Abekho othintana nabo abakhethiwe."</string>
+ <!-- no translation found for add_field (2384260056674995230) -->
+ <skip />
+ <!-- no translation found for add_phone (4421904942555210013) -->
+ <skip />
+ <!-- no translation found for add_email (175079666329862215) -->
+ <skip />
+ <!-- no translation found for add_im (5158094627521120439) -->
+ <skip />
+ <!-- no translation found for add_address (418292312672970688) -->
+ <skip />
+ <!-- no translation found for add_note (2753771325725383279) -->
+ <skip />
+ <!-- no translation found for add_website (4312391288948517344) -->
+ <skip />
+ <!-- no translation found for add_event (7488781591843886426) -->
+ <skip />
+ <!-- no translation found for add_relationship (3083762399737240006) -->
+ <skip />
+ <string name="contact_status_update_attribution" msgid="752179367353018597">"nge <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
+ <string name="contact_status_update_attribution_with_date" msgid="7358045508107825068">"<xliff:g id="DATE">%1$s</xliff:g> nge- <xliff:g id="SOURCE">%2$s</xliff:g>"</string>
+ <string name="description_star" msgid="2605854427360036550">"intandokazi"</string>
+ <string name="edit_contact" msgid="7529281274005689512">"Hlela othintana naye"</string>
+ <plurals name="merge_info">
+ <item quantity="one" msgid="148365587896371969">"akuhlanganisiwe"</item>
+ <item quantity="other" msgid="425683718017380845">"ihlanganiswe kusuka emithombeni engu-<xliff:g id="COUNT">%0$d</xliff:g>"</item>
+ </plurals>
+ <string name="local_invisible_directory" msgid="6046691709127661065">"Okunye"</string>
+ <!-- no translation found for aggregation_suggestion_join_dialog_title (5276699501316246253) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_join_dialog_message (3842757977671434836) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_title (1064042382692091314) -->
+ <skip />
+ <!-- no translation found for aggregation_suggestion_edit_dialog_message (6549585283910518095) -->
+ <skip />
+ <string name="menu_copyContact" msgid="4401683725471696686">"Kopisha kwengithintana nabo"</string>
+ <!-- no translation found for contact_directory_description (683398073603909119) -->
+ <skip />
+ <!-- no translation found for search_label (6789295859496641042) -->
+ <skip />
+ <string name="directory_search_label" msgid="1887759056597975053">"Uhla lwemibhalo"</string>
+ <string name="local_search_label" msgid="1686089693064201315">"Othintana nabo"</string>
+ <string name="toast_making_personal_copy" msgid="7905283986345263275">"Idala ikhophi yomuntu siqu"</string>
+ <string name="list_filter_prompt" msgid="7481426622828055116">"Khetha uhlu lothintana naye"</string>
+ <string name="list_filter_all_accounts" msgid="8908683398914322369">"Bonke othintana nabo"</string>
+ <!-- no translation found for list_filter_all_starred (5031734941601931356) -->
+ <skip />
+ <!-- no translation found for list_filter_custom (8910173055702057002) -->
+ <skip />
+ <string name="list_filter_customize" msgid="2035084418635775579">"Enza ngendlela oyifisayo..."</string>
+ <!-- no translation found for list_filter_phones (7905045603593508221) -->
+ <skip />
+ <!-- no translation found for list_filter_single (5871400283515893087) -->
+ <skip />
+ <!-- no translation found for custom_list_filter (7836035257402013957) -->
+ <skip />
+ <string name="activity_title_settings" msgid="5464130076132770781">"Izilungiselelo"</string>
+ <string name="menu_settings" msgid="377929915873428211">"Izilungiselelo"</string>
+ <string name="preference_displayOptions" msgid="1341720270148252393">"Bonisa okukhethwa kukho"</string>
+ <!-- no translation found for organization_company_and_title (6718207751363732025) -->
+ <skip />
+ <!-- no translation found for hint_findContacts (1808681193458772072) -->
+ <skip />
+ <!-- no translation found for non_phone_caption (1541655052330027380) -->
+ <skip />
+ <!-- no translation found for non_phone_add_to_contacts (6590985286250471169) -->
+ <skip />
+ <!-- no translation found for non_phone_close (7608506439725515667) -->
+ <skip />
+ <!-- no translation found for widget_name_and_phonetic (8739586586600099979) -->
+ <skip />
+ <!-- no translation found for date_year_toggle (7356532842767854606) -->
+ <skip />
+ <!-- no translation found for social_widget_label (6378905543028924592) -->
+ <skip />
+ <!-- no translation found for social_widget_loading (3697996166985327861) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_create_contact (7014525713871959208) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_add_account (7911101713860139754) -->
+ <skip />
+ <!-- no translation found for contacts_unavailable_import_contacts (4456440183590517471) -->
+ <skip />
+ <!-- no translation found for create_group_dialog_title (6874527142828424475) -->
+ <skip />
+ <!-- no translation found for create_group_item_label (5218022006186243310) -->
+ <skip />
+ <!-- no translation found for rename_group_dialog_title (3765299704290513289) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_title (7368429698398624427) -->
+ <skip />
+ <!-- no translation found for delete_group_dialog_message (295063284548750881) -->
+ <skip />
+ <!-- no translation found for toast_join_with_empty_contact (5015189525953438968) -->
+ <skip />
+ <!-- no translation found for indicator_joined_contact (3321049349627022128) -->
+ <skip />
+ <!-- no translation found for toast_text_copied (5143776250008541719) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_title (3950463632415908534) -->
+ <skip />
+ <!-- no translation found for cancel_confirmation_dialog_message (7021968394611740251) -->
+ <skip />
+ <!-- no translation found for discard (1234315037371251414) -->
+ <skip />
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 69f92ad..ace8869 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -21,10 +21,16 @@
<color name="quickcontact_disambig_divider">#afafaf</color>
<color name="edit_divider">#ff666666</color>
+
+ <!-- Color of the background of the contact detail and editor pages -->
+ <color name="background_primary">#FFFFFF</color>
+
<color name="background_secondary">#ff202020</color>
<color name="translucent_search_background">#cc000000</color>
+ <color name="account_selection_background">#ff000000</color>
+
<!-- Color used for the letter in the A-Z section header -->
<color name="section_header_text_color">#ff999999</color>
@@ -39,4 +45,7 @@
<!-- Color of the text indicating the type of entry (e.g. Home, Work etc) -->
<color name="detail_item_type_color">#B4B4B4</color>
+
+ <!-- Color of the text indicating the type of entry (e.g. Home, Work etc) -->
+ <color name="detail_header_view_text_color">#FFFFFF</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3aca306..ff7d873 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
<resources>
- <dimen name="edit_photo_size">76dip</dimen>
+ <dimen name="edit_photo_size">120dip</dimen>
<!-- The height of the ScrollingTabWidget -->
<dimen name="tab_height">40dip</dimen>
@@ -26,6 +26,9 @@
<dimen name="aggregation_suggestion_icon_size">40dip</dimen>
<dimen name="account_selector_popup_width">400dip</dimen>
+ <dimen name="account_selector_icon_size">30dip</dimen>
+ <dimen name="account_selector_min_item_height">48dip</dimen>
+ <dimen name="account_selector_horizontal_margin">6dip</dimen>
<dimen name="photo_action_popup_width">400dip</dimen>
@@ -35,38 +38,53 @@
<dimen name="quick_contact_width">352dip</dimen>
<!-- Padding of the rounded plus/minus/expand/collapse buttons in the editor -->
- <dimen name="editor_round_button_padding_left">2dip</dimen>
- <dimen name="editor_round_button_padding_right">2dip</dimen>
+ <dimen name="editor_round_button_padding_left">4dip</dimen>
+ <dimen name="editor_round_button_padding_right">4dip</dimen>
<dimen name="editor_round_button_padding_top">8dip</dimen>
<dimen name="editor_round_button_padding_bottom">8dip</dimen>
+ <!-- Font size for the structured name in the contact detail page -->
+ <dimen name="editor_structured_name_text_size">25sp</dimen>
+
<!-- Width of the Type-Label in the Editor -->
- <dimen name="editor_type_label_width">140dip</dimen>
-
+ <dimen name="editor_type_label_width">120dip</dimen>
+
+ <!-- Left padding of a field in the Editor -->
+ <dimen name="editor_field_left_padding">5dip</dimen>
+
+ <!-- Top padding of a field in the Editor -->
+ <dimen name="editor_field_top_padding">10dip</dimen>
+
+ <!-- Bottom padding of a field in the Editor -->
+ <dimen name="editor_field_bottom_padding">5dip</dimen>
+
<!-- Minimum height of a row in the Editor -->
<dimen name="editor_min_line_item_height">48dip</dimen>
- <!-- Left margin of the name text input fields and the photo in the contact editor -->
- <dimen name="editor_name_text_field_left_margin">25dip</dimen>
+ <!-- Font size used for the value of a field in the contact editor. -->
+ <dimen name="editor_field_text_size">18sp</dimen>
- <!-- Right margin of the text input fields in the contact editor -->
- <dimen name="editor_name_text_field_right_margin">0dip</dimen>
+ <!-- Font size used for the title of a field in the contact editor. -->
+ <dimen name="editor_field_title_text_size">15sp</dimen>
- <!-- Width of the title labels in the contact editor -->
- <dimen name="editor_title_label_width">120dip</dimen>
+ <!-- Font size for the entries in a spinner in the contact editor. -->
+ <dimen name="editor_field_spinner_text_size">10sp</dimen>
- <!-- Interpolator layout narrow width value of the contact editor -->
- <dimen name="editor_interpolator_narrow_width">600dip</dimen>
+ <!-- Left and right padding for a contact detail item -->
+ <dimen name="detail_item_icon_margin">10dip</dimen>
- <!-- Height of the attribution text view in the contact detail header view -->
- <dimen name="detail_header_attribution_height">40dip</dimen>
-
- <!-- Margin between the photo, the star, and text in the contact detail header view -->
- <dimen name="detail_header_view_margin">8dip</dimen>
+ <!-- Left and right padding for a contact detail item -->
+ <dimen name="detail_item_side_margin">10dip</dimen>
<!-- Minimum height of a row in the contact detail -->
<dimen name="detail_min_line_item_height">48dip</dimen>
+ <!-- Width of a contact detail item type (i.e. Nickname or Website). -->
+ <dimen name="detail_item_type_width">164dip</dimen>
+
+ <!-- Font size for the display name in header of the contact detail page -->
+ <dimen name="detail_header_name_text_size">30sp</dimen>
+
<!-- Padding to be used between a visible scrollbar and the contact list -->
<dimen name="list_visible_scrollbar_padding">40dip</dimen>
@@ -76,9 +94,6 @@
<!-- Font size used for the social status in the widget -->
<dimen name="widget_text_size_snippet">13sp</dimen>
- <!-- Font size used for the contact name in the detail and the editor -->
- <dimen name="contact_name_text_size">18sp</dimen>
-
<!-- Minimum width of the filter selector in the action bar -->
<dimen name="action_bar_filter_min_width">100dip</dimen>
@@ -93,4 +108,7 @@
<!-- Size of the shortcut icon. 0dip means: use the system default -->
<dimen name="shortcut_icon_size">0dip</dimen>
+
+ <!-- Height of list sections (A, B, C) that show the first character of the contacts -->
+ <dimen name="list_section_height">25dip</dimen>
</resources>
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index f5efa13..e310953 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -99,4 +99,8 @@
<!-- If true, phonetic name is included in the contact editor by default -->
<bool name="config_editor_include_phonetic_name">false</bool>
+
+ <!-- If true, Contacts uses two panes: List and Detail. If false, Details are
+ shown in their own screens. This flag must be in sync with the layout definitions. -->
+ <bool name="config_use_two_panes">false</bool>
</resources>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 1a553d1..2de327a 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -18,7 +18,6 @@
<item type="id" name="data"/>
<item type="id" name="header_phones"/>
<item type="id" name="dialog_sync_add"/>
- <item type="id" name="dialog_import_export"/>
<!-- For vcard.ImportVCardActivity -->
<item type="id" name="dialog_searching_vcard"/>
@@ -39,9 +38,6 @@
<item type="id" name="dialog_delete_contact_confirmation"/>
<item type="id" name="dialog_delete_contact_loader_id" />
- <!-- For ImportExportInteraction -->
- <item type="id" name="dialog_import_export_options"/>
-
<!-- For ExportVCardActivity -->
<item type="id" name="dialog_export_confirmation"/>
<item type="id" name="dialog_exporting_vcard"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2d515a7..2f9acb4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -18,14 +18,17 @@
apps sharing the uid). -->
<string name="sharedUserLabel">Android Core Apps</string>
- <!-- Title for the activity that shows contacts. This is the name
- used in the Launcher icon. -->
- <string name="contactsList">Contacts</string>
-
<!-- Title for the activity that dials the phone. This is the name
used in the Launcher icon. -->
<string name="launcherDialer">Phone</string>
+ <!-- Title for the activity that opens the People app. This is the name
+ used in the Launcher icon. -->
+ <string name="people">People</string>
+
+ <!-- Directory partition name -->
+ <string name="contactsList">Contacts</string>
+
<!-- Name of activity that allows users to create shortcuts on the home screen to a contact.
This shows up in a list of things like bookmark, folder, music playlist, etc -->
<string name="shortcutContact">Contact</string>
@@ -264,6 +267,9 @@
<!-- The text displayed when the contacts list is empty while displaying all contacts -->
<string name="noContacts">No contacts.</string>
+ <!-- The text displayed when the groups list is empty while displaying all groups [CHAR LIMIT=NONE] -->
+ <string name="noGroups">No groups.</string>
+
<!-- The text displayed when the contacts list is empty while displaying results after searching contacts -->
<string name="noMatchingContacts">No matching contacts found.</string>
@@ -349,6 +355,9 @@
<!-- The description text for the contacts tab. Space is limited for this string, so the shorter the better -->
<string name="contactsIconLabel">Contacts</string>
+ <!-- The description text for the groups tab. Space is limited for this string, so the shorter the better -->
+ <string name="contactsGroupsLabel">Groups</string>
+
<!-- The description text for the favorites tab. Space is limited for this string, so the shorter the better -->
<string name="contactsFavoritesLabel">Favorites</string>
@@ -388,6 +397,9 @@
<!-- Confirmation dialog for clearing the call log -->
<string name="clearCallLogConfirmation">Are you sure you want to clear the call log?</string>
+ <!-- Title of the "Clearing call log" progress-dialog [CHAR LIMIT=35] -->
+ <string name="clearCallLogProgress_title">Clearing call log</string>
+
<!-- The title of a dialog that displays the IMEI of the phone -->
<string name="imei">IMEI</string>
@@ -1219,7 +1231,7 @@
<string name="account_type_format"><xliff:g id="source" example="Gmail">%1$s</xliff:g> contact</string>
<!-- String describing which account a contact came from when editing it -->
- <string name="from_account_format">from <xliff:g id="source" example="user@gmail.com">%1$s</xliff:g></string>
+ <string name="from_account_format"><xliff:g id="source" example="user@gmail.com">%1$s</xliff:g></string>
<!-- Checkbox asking the user if they want to display a particular photo for a contact -->
<string name="use_photo_as_primary">Use this photo</string>
@@ -1312,6 +1324,30 @@
<!-- The add field button shown in the editor under each editable Raw Contact [CHAR LIMIT=30] -->
<string name="add_field">Add another field</string>
+ <!-- The editable field hint text to add a new phone number to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_phone">Add new phone number</string>
+
+ <!-- The editable field hint text to add a new email to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_email">Add new email</string>
+
+ <!-- The editable field hint text to add a new IM account to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_im">Add new IM account</string>
+
+ <!-- The editable field hint text to add a new postal address to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_address">Add new address</string>
+
+ <!-- The editable field hint text to add a new note to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_note">Add new note</string>
+
+ <!-- The editable field hint text to add a new website to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_website">Add new website</string>
+
+ <!-- The editable field hint text to add a new event to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_event">Add new event</string>
+
+ <!-- The editable field hint text to add a relationship field to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
+ <string name="add_relationship">Add new relationship</string>
+
<!-- Attbution of a contact status update, when the time of update is unknown -->
<string name="contact_status_update_attribution">via <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1b494af..df8b808 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -14,18 +14,37 @@
limitations under the License.
-->
<resources>
- <style name="DialtactsTheme" parent="@android:Theme">
- <item name="android:windowNoTitle">true</item>
+ <style name="DialtactsTheme" parent="android:Theme.Holo.Light">
<item name="android:windowContentOverlay">@null</item>
+ <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
+ <item name="activated_background">@drawable/list_item_activated_background</item>
+ <item name="section_header_background">@drawable/list_title_holo</item>
+ <item name="list_section_header_height">32dip</item>
+ <item name="list_item_divider">@drawable/list_item_divider</item>
+ <item name="list_item_padding_top">4dip</item>
+ <item name="list_item_padding_right">11dip</item>
+ <item name="list_item_padding_bottom">4dip</item>
+ <item name="list_item_padding_left">4dip</item>
+ <item name="list_item_gap_between_image_and_text">8dip</item>
+ <item name="list_item_gap_between_label_and_data">5dip</item>
+ <item name="list_item_call_button_padding">14dip</item>
+ <item name="list_item_vertical_divider_margin">5dip</item>
+ <item name="list_item_presence_icon_margin">5dip</item>
+ <item name="list_item_photo_size">56dip</item>
+ <item name="list_item_prefix_highlight_color">#729a27</item>
+ <item name="list_item_header_text_indent">56dip</item>
+ <item name="list_item_header_text_color">?color/section_header_text_color</item>
+ <item name="list_item_header_text_size">14sp</item>
+ <item name="contact_filter_popup_width">320dip</item>
</style>
- <style name="CallDetailActivityTheme" parent="android:Theme.NoTitleBar">
+ <style name="CallDetailActivityTheme" parent="android:Theme.Holo.Light">
<item name="android:windowContentOverlay">@null</item>
</style>
- <style name="ContactDetailActivityTheme" parent="android:Theme.NoTitleBar">
+ <style name="ContactDetailActivityTheme" parent="android:Theme.Holo.Light">
<item name="android:windowContentOverlay">@null</item>
</style>
- <style name="ContactEditorActivityTheme" parent="android:Theme.NoTitleBar">
+ <style name="ContactEditorActivityTheme" parent="android:Theme.Holo.Light">
<item name="android:windowContentOverlay">@null</item>
</style>
@@ -38,38 +57,19 @@
<item name="android:windowIsFloating">true</item>
</style>
- <style name="FullyTranslucent" parent="android:Theme.Translucent.NoTitleBar">
- <item name="android:windowContentOverlay">@null</item>
+ <style name="Theme">
</style>
- <style name="FullyTranslucent.QuickContact">
- <!-- This is a hack because we want to be able to animate away the
- QuickContact window, and we close its containing activity at the
- same time. So put in a dummy animation so this guy sticks around
- while the fast track window is animating. -->
- <item name="android:windowAnimationStyle">@style/DummyAnimation</item>
- </style>
-
- <style name="QuickContact" parent="@android:Theme.Holo.Light">
- <item name="android:windowNoTitle">true</item>
- <item name="android:windowFrame">@null</item>
+ <style name="Theme.QuickContact" parent="@android:style/Theme.Holo.Light">
<item name="android:windowBackground">@android:color/transparent</item>
- <item name="android:windowIsFloating">true</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
- <!-- TODO: create our own animation style in framework -->
- <!--
- <item name="android:windowAnimationStyle">@*android:style/Animation.ZoomButtons</item>
- -->
- </style>
-
- <style name="QuickContactAboveAnimation">
- <item name="android:windowEnterAnimation">@anim/quickcontact_above_enter</item>
- <item name="android:windowExitAnimation">@anim/quickcontact_above_exit</item>
- </style>
-
- <style name="QuickContactBelowAnimation">
- <item name="android:windowEnterAnimation">@anim/quickcontact_below_enter</item>
- <item name="android:windowExitAnimation">@anim/quickcontact_below_exit</item>
+ <item name="android:windowAnimationStyle">@null</item>
+ <item name="android:windowIsFloating">false</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowNoTitle">true</item>
</style>
<style name="ContactsSearchAnimation">
@@ -95,7 +95,6 @@
<attr name="list_item_padding_right" format="dimension"/>
<attr name="list_item_padding_bottom" format="dimension"/>
<attr name="list_item_padding_left" format="dimension"/>
- <attr name="list_item_fading_edge_length" format="dimension"/>
<attr name="list_item_gap_between_image_and_text" format="dimension"/>
<attr name="list_item_gap_between_label_and_data" format="dimension"/>
<attr name="list_item_call_button_padding" format="dimension"/>
@@ -108,17 +107,40 @@
<attr name="list_item_header_text_size" format="dimension" />
</declare-styleable>
- <style name="ContactBrowserTheme" parent="@android:Theme">
+ <style name="PeopleTheme" parent="@android:Theme">
<item name="list_item_height">?android:attr/listPreferredItemHeight</item>
<item name="activated_background">@drawable/list_item_activated_background</item>
- <item name="section_header_background">@drawable/section_header</item>
+ <item name="section_header_background">@drawable/list_title_holo</item>
<item name="list_section_header_height">32dip</item>
<item name="list_item_divider">@drawable/list_item_divider</item>
<item name="list_item_padding_top">4dip</item>
<item name="list_item_padding_right">11dip</item>
<item name="list_item_padding_bottom">4dip</item>
<item name="list_item_padding_left">4dip</item>
- <item name="list_item_fading_edge_length">5dip</item>
+ <item name="list_item_gap_between_image_and_text">8dip</item>
+ <item name="list_item_gap_between_label_and_data">5dip</item>
+ <item name="list_item_call_button_padding">14dip</item>
+ <item name="list_item_vertical_divider_margin">5dip</item>
+ <item name="list_item_presence_icon_margin">5dip</item>
+ <item name="list_item_photo_size">56dip</item>
+ <item name="list_item_prefix_highlight_color">#729a27</item>
+ <item name="list_item_header_text_indent">56dip</item>
+ <item name="list_item_header_text_color">?color/section_header_text_color</item>
+ <item name="list_item_header_text_size">14sp</item>
+ <item name="contact_filter_popup_width">320dip</item>
+ </style>
+
+ <!-- TODO: Clean up this file so themes aren't copied. -->
+ <style name="GroupDetailTheme" parent="@android:Theme">
+ <item name="list_item_height">?android:attr/listPreferredItemHeight</item>
+ <item name="activated_background">@drawable/list_item_activated_background</item>
+ <item name="section_header_background">@drawable/list_title_holo</item>
+ <item name="list_section_header_height">32dip</item>
+ <item name="list_item_divider">@drawable/list_item_divider</item>
+ <item name="list_item_padding_top">4dip</item>
+ <item name="list_item_padding_right">11dip</item>
+ <item name="list_item_padding_bottom">4dip</item>
+ <item name="list_item_padding_left">4dip</item>
<item name="list_item_gap_between_image_and_text">8dip</item>
<item name="list_item_gap_between_label_and_data">5dip</item>
<item name="list_item_call_button_padding">14dip</item>
@@ -154,7 +176,7 @@
<style name="JoinContactActivityTheme" parent="ContactPickerTheme" >
</style>
- <style name="ContactsPreferencesTheme" parent="@android:Theme">
+ <style name="ContactsPreferencesTheme" parent="@android:Theme.Holo.Light">
</style>
<style name="CustomContactListFilterTheme" parent="@android:Theme">
@@ -195,7 +217,7 @@
<attr name="animationDuration" format="integer"/>
</declare-styleable>
- <style name="DirectoryHeader" parent="ContactBrowserTheme">
+ <style name="DirectoryHeader" parent="PeopleTheme">
<item name="android:background">@drawable/directory_bg</item>
</style>
@@ -211,8 +233,14 @@
<item name="android:layout_width">match_parent</item>
</style>
- <style name="ContactDetailHeaderTextView">
- <item name="android:layout_width">match_parent</item>
+ <style name="ContactDetailItemType">
+ <item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ <item name="android:textColor">@color/detail_item_type_color</item>
+ <item name="android:singleLine">true</item>
+ <item name="android:ellipsize">marquee</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:paddingTop">5dip</item>
</style>
</resources>
diff --git a/src/com/android/contacts/ContactLoader.java b/src/com/android/contacts/ContactLoader.java
index f4baf3b..4b0bbaa 100644
--- a/src/com/android/contacts/ContactLoader.java
+++ b/src/com/android/contacts/ContactLoader.java
@@ -93,6 +93,7 @@
private final long mPhotoId;
private final String mPhotoUri;
private final String mDisplayName;
+ private final String mAltDisplayName;
private final String mPhoneticName;
private final boolean mStarred;
private final Integer mPresence;
@@ -131,6 +132,7 @@
mPhotoId = -1;
mPhotoUri = null;
mDisplayName = null;
+ mAltDisplayName = null;
mPhoneticName = null;
mStarred = false;
mPresence = null;
@@ -145,8 +147,9 @@
*/
private Result(Uri uri, Uri lookupUri, long directoryId, String lookupKey, long id,
long nameRawContactId, int displayNameSource, long photoId, String photoUri,
- String displayName, String phoneticName, boolean starred, Integer presence,
- String status, Long statusTimestamp, Integer statusLabel, String statusResPackage) {
+ String displayName, String altDisplayName, String phoneticName, boolean starred,
+ Integer presence, String status, Long statusTimestamp, Integer statusLabel,
+ String statusResPackage) {
mLookupUri = lookupUri;
mUri = uri;
mDirectoryId = directoryId;
@@ -159,6 +162,7 @@
mPhotoId = photoId;
mPhotoUri = photoUri;
mDisplayName = displayName;
+ mAltDisplayName = altDisplayName;
mPhoneticName = phoneticName;
mStarred = starred;
mPresence = presence;
@@ -179,6 +183,7 @@
mPhotoId = from.mPhotoId;
mPhotoUri = from.mPhotoUri;
mDisplayName = from.mDisplayName;
+ mAltDisplayName = from.mAltDisplayName;
mPhoneticName = from.mPhoneticName;
mStarred = from.mStarred;
mPresence = from.mPresence;
@@ -257,6 +262,10 @@
return mDisplayName;
}
+ public String getAltDisplayName() {
+ return mAltDisplayName;
+ }
+
public String getPhoneticName() {
return mPhoneticName;
}
@@ -380,6 +389,7 @@
Contacts.DISPLAY_NAME_SOURCE,
Contacts.LOOKUP_KEY,
Contacts.DISPLAY_NAME,
+ Contacts.DISPLAY_NAME_ALTERNATIVE,
Contacts.PHONETIC_NAME,
Contacts.PHOTO_ID,
Contacts.STARRED,
@@ -447,67 +457,68 @@
public final static int DISPLAY_NAME_SOURCE = 1;
public final static int LOOKUP_KEY = 2;
public final static int DISPLAY_NAME = 3;
- public final static int PHONETIC_NAME = 4;
- public final static int PHOTO_ID = 5;
- public final static int STARRED = 6;
- public final static int CONTACT_PRESENCE = 7;
- public final static int CONTACT_STATUS = 8;
- public final static int CONTACT_STATUS_TIMESTAMP = 9;
- public final static int CONTACT_STATUS_RES_PACKAGE = 10;
- public final static int CONTACT_STATUS_LABEL = 11;
- public final static int CONTACT_ID = 12;
- public final static int RAW_CONTACT_ID = 13;
+ public final static int ALT_DISPLAY_NAME = 4;
+ public final static int PHONETIC_NAME = 5;
+ public final static int PHOTO_ID = 6;
+ public final static int STARRED = 7;
+ public final static int CONTACT_PRESENCE = 8;
+ public final static int CONTACT_STATUS = 9;
+ public final static int CONTACT_STATUS_TIMESTAMP = 10;
+ public final static int CONTACT_STATUS_RES_PACKAGE = 11;
+ public final static int CONTACT_STATUS_LABEL = 12;
+ public final static int CONTACT_ID = 13;
+ public final static int RAW_CONTACT_ID = 14;
- public final static int ACCOUNT_NAME = 14;
- public final static int ACCOUNT_TYPE = 15;
- public final static int DIRTY = 16;
- public final static int VERSION = 17;
- public final static int SOURCE_ID = 18;
- public final static int SYNC1 = 19;
- public final static int SYNC2 = 20;
- public final static int SYNC3 = 21;
- public final static int SYNC4 = 22;
- public final static int DELETED = 23;
- public final static int IS_RESTRICTED = 24;
- public final static int NAME_VERIFIED = 25;
+ public final static int ACCOUNT_NAME = 15;
+ public final static int ACCOUNT_TYPE = 16;
+ public final static int DIRTY = 17;
+ public final static int VERSION = 18;
+ public final static int SOURCE_ID = 19;
+ public final static int SYNC1 = 20;
+ public final static int SYNC2 = 21;
+ public final static int SYNC3 = 22;
+ public final static int SYNC4 = 23;
+ public final static int DELETED = 24;
+ public final static int IS_RESTRICTED = 25;
+ public final static int NAME_VERIFIED = 26;
- public final static int DATA_ID = 26;
- public final static int DATA1 = 27;
- public final static int DATA2 = 28;
- public final static int DATA3 = 29;
- public final static int DATA4 = 30;
- public final static int DATA5 = 31;
- public final static int DATA6 = 32;
- public final static int DATA7 = 33;
- public final static int DATA8 = 34;
- public final static int DATA9 = 35;
- public final static int DATA10 = 36;
- public final static int DATA11 = 37;
- public final static int DATA12 = 38;
- public final static int DATA13 = 39;
- public final static int DATA14 = 40;
- public final static int DATA15 = 41;
- public final static int DATA_SYNC1 = 42;
- public final static int DATA_SYNC2 = 43;
- public final static int DATA_SYNC3 = 44;
- public final static int DATA_SYNC4 = 45;
- public final static int DATA_VERSION = 46;
- public final static int IS_PRIMARY = 47;
- public final static int IS_SUPERPRIMARY = 48;
- public final static int MIMETYPE = 49;
- public final static int RES_PACKAGE = 50;
+ public final static int DATA_ID = 27;
+ public final static int DATA1 = 28;
+ public final static int DATA2 = 29;
+ public final static int DATA3 = 30;
+ public final static int DATA4 = 31;
+ public final static int DATA5 = 32;
+ public final static int DATA6 = 33;
+ public final static int DATA7 = 34;
+ public final static int DATA8 = 35;
+ public final static int DATA9 = 36;
+ public final static int DATA10 = 37;
+ public final static int DATA11 = 38;
+ public final static int DATA12 = 39;
+ public final static int DATA13 = 40;
+ public final static int DATA14 = 41;
+ public final static int DATA15 = 42;
+ public final static int DATA_SYNC1 = 43;
+ public final static int DATA_SYNC2 = 44;
+ public final static int DATA_SYNC3 = 45;
+ public final static int DATA_SYNC4 = 46;
+ public final static int DATA_VERSION = 47;
+ public final static int IS_PRIMARY = 48;
+ public final static int IS_SUPERPRIMARY = 49;
+ public final static int MIMETYPE = 50;
+ public final static int RES_PACKAGE = 51;
- public final static int GROUP_SOURCE_ID = 51;
+ public final static int GROUP_SOURCE_ID = 52;
- public final static int PRESENCE = 52;
- public final static int CHAT_CAPABILITY = 53;
- public final static int STATUS = 54;
- public final static int STATUS_RES_PACKAGE = 55;
- public final static int STATUS_ICON = 56;
- public final static int STATUS_LABEL = 57;
- public final static int STATUS_TIMESTAMP = 58;
+ public final static int PRESENCE = 53;
+ public final static int CHAT_CAPABILITY = 54;
+ public final static int STATUS = 55;
+ public final static int STATUS_RES_PACKAGE = 56;
+ public final static int STATUS_ICON = 57;
+ public final static int STATUS_LABEL = 58;
+ public final static int STATUS_TIMESTAMP = 59;
- public final static int PHOTO_URI = 59;
+ public final static int PHOTO_URI = 60;
}
private static class DirectoryQuery {
@@ -699,6 +710,7 @@
final long nameRawContactId = cursor.getLong(ContactQuery.NAME_RAW_CONTACT_ID);
final int displayNameSource = cursor.getInt(ContactQuery.DISPLAY_NAME_SOURCE);
final String displayName = cursor.getString(ContactQuery.DISPLAY_NAME);
+ final String altDisplayName = cursor.getString(ContactQuery.ALT_DISPLAY_NAME);
final String phoneticName = cursor.getString(ContactQuery.PHONETIC_NAME);
final long photoId = cursor.getLong(ContactQuery.PHOTO_ID);
final String photoUri = cursor.getString(ContactQuery.PHOTO_URI);
@@ -726,8 +738,8 @@
return new Result(contactUri, lookupUri, directoryId, lookupKey, contactId,
nameRawContactId, displayNameSource, photoId, photoUri, displayName,
- phoneticName, starred, presence, status, statusTimestamp, statusLabel,
- statusResPackage);
+ altDisplayName, phoneticName, starred, presence, status, statusTimestamp,
+ statusLabel, statusResPackage);
}
/**
diff --git a/src/com/android/contacts/ContactPhotoManager.java b/src/com/android/contacts/ContactPhotoManager.java
index 914b697..150856a 100644
--- a/src/com/android/contacts/ContactPhotoManager.java
+++ b/src/com/android/contacts/ContactPhotoManager.java
@@ -625,12 +625,13 @@
try {
Uri uri = Contacts.CONTENT_URI.buildUpon().appendQueryParameter(
ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT))
+ .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY,
+ String.valueOf(MAX_PHOTOS_TO_PRELOAD))
.build();
cursor = mResolver.query(uri, new String[] { Contacts.PHOTO_ID },
Contacts.PHOTO_ID + " NOT NULL AND " + Contacts.PHOTO_ID + "!=0",
null,
- Contacts.STARRED + " DESC, " + Contacts.LAST_TIME_CONTACTED + " DESC"
- + " LIMIT " + MAX_PHOTOS_TO_PRELOAD);
+ Contacts.STARRED + " DESC, " + Contacts.LAST_TIME_CONTACTED + " DESC");
if (cursor != null) {
while (cursor.moveToNext()) {
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 0e75a7f..76cbc7d 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -16,6 +16,11 @@
package com.android.contacts;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
import android.content.Context;
import android.content.Intent;
import android.location.CountryDetector;
@@ -114,9 +119,19 @@
if (dataParts1.length != dataParts2.length) {
return false;
}
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
for (int i = 0; i < dataParts1.length; i++) {
- if (!PhoneNumberUtils.compare(context, dataParts1[i], dataParts2[i])) {
- return false;
+ try {
+ PhoneNumber phoneNumber1 = util.parse(dataParts1[i], "ZZ" /* Unknown */);
+ PhoneNumber phoneNumber2 = util.parse(dataParts2[i], "ZZ" /* Unknown */);
+ MatchType matchType = util.isNumberMatch(phoneNumber1, phoneNumber2);
+ if (matchType != MatchType.SHORT_NSN_MATCH) {
+ return false;
+ }
+ } catch (NumberParseException e) {
+ if (!TextUtils.equals(dataParts1[i], dataParts2[i])) {
+ return false;
+ }
}
}
diff --git a/src/com/android/contacts/DialtactsActivity.java b/src/com/android/contacts/DialtactsActivity.java
deleted file mode 100644
index dc69194..0000000
--- a/src/com/android/contacts/DialtactsActivity.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import com.android.contacts.activities.ContactsFrontDoor;
-import com.android.contacts.activities.ContactBrowserActivity;
-import com.android.internal.telephony.ITelephony;
-
-import android.app.Activity;
-import android.app.TabActivity;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.provider.CallLog.Calls;
-import android.provider.ContactsContract.Intents.UI;
-import android.util.Log;
-import android.view.Window;
-import android.widget.TabHost;
-
-/**
- * The dialer activity that has one tab with the virtual 12key
- * dialer, a tab with recent calls in it, a tab with the contacts and
- * a tab with the favorite. This is the container and the tabs are
- * embedded using intents.
- * The dialer tab's title is 'phone', a more common name (see strings.xml).
- */
-public class DialtactsActivity extends TabActivity implements TabHost.OnTabChangeListener {
- private static final String TAG = "Dailtacts";
-
- private static final int TAB_INDEX_DIALER = 0;
- private static final int TAB_INDEX_CALL_LOG = 1;
- private static final int TAB_INDEX_CONTACTS = 2;
- private static final int TAB_INDEX_FAVORITES = 3;
-
- static final String EXTRA_IGNORE_STATE = "ignore-state";
-
- /** Name of the dialtacts shared preferences */
- static final String PREFS_DIALTACTS = "dialtacts";
- /** If true, when handling the contacts intent the favorites tab will be shown instead */
- static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts";
- static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
-
- /** Last manually selected tab index */
- private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
- private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
-
- private TabHost mTabHost;
- private String mFilterText;
- private Uri mDialUri;
-
- /**
- * The index of the tab that has last been manually selected (the user clicked on a tab).
- * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call)
- */
- private int mLastManuallySelectedTab;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- final Intent intent = getIntent();
- fixIntent(intent);
-
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.dialer_activity);
-
- mTabHost = getTabHost();
- mTabHost.setOnTabChangedListener(this);
-
- // Setup the tabs
- setupDialerTab();
- setupCallLogTab();
- setupContactsTab();
- setupFavoritesTab();
-
- // Load the last manually loaded tab
- final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
- mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
- PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
-
- setCurrentTab(intent);
-
- if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction())
- && icicle == null) {
- setupFilterText(intent);
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- final int currentTabIndex = mTabHost.getCurrentTab();
- final SharedPreferences.Editor editor =
- getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
- if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) {
- editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES);
- }
- editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab);
-
- editor.apply();
- }
-
- private void fixIntent(Intent intent) {
- // This should be cleaned up: the call key used to send an Intent
- // that just said to go to the recent calls list. It now sends this
- // abstract action, but this class hasn't been rewritten to deal with it.
- if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
- intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
- intent.putExtra("call_key", true);
- setIntent(intent);
- }
- }
-
- private void setupCallLogTab() {
- // Force the class since overriding tab entries doesn't work
- Intent intent = new Intent("com.android.phone.action.RECENT_CALLS");
- intent.setClass(this, RecentCallsListActivity.class);
-
- mTabHost.addTab(mTabHost.newTabSpec("call_log")
- .setIndicator(getString(R.string.recentCallsIconLabel),
- getResources().getDrawable(R.drawable.ic_tab_recent))
- .setContent(intent));
- }
-
- private void setupDialerTab() {
- Intent intent = new Intent("com.android.phone.action.TOUCH_DIALER");
- intent.setClass(this, TwelveKeyDialer.class);
-
- mTabHost.addTab(mTabHost.newTabSpec("dialer")
- .setIndicator(getString(R.string.dialerIconLabel),
- getResources().getDrawable(R.drawable.ic_tab_dialer))
- .setContent(intent));
- }
-
- private void setupContactsTab() {
- Intent intent = new Intent(UI.LIST_DEFAULT);
- intent.setClass(this, ContactBrowserActivity.class);
-
- mTabHost.addTab(mTabHost.newTabSpec("contacts")
- .setIndicator(getText(R.string.contactsIconLabel),
- getResources().getDrawable(R.drawable.ic_tab_contacts))
- .setContent(intent));
- }
-
- private void setupFavoritesTab() {
- Intent intent = new Intent(UI.LIST_STREQUENT_ACTION);
- intent.setClass(this, ContactBrowserActivity.class);
-
- mTabHost.addTab(mTabHost.newTabSpec("favorites")
- .setIndicator(getString(R.string.contactsFavoritesLabel),
- getResources().getDrawable(R.drawable.ic_tab_starred))
- .setContent(intent));
- }
-
- /**
- * Returns true if the intent is due to hitting the green send key while in a call.
- *
- * @param intent the intent that launched this activity
- * @param recentCallsRequest true if the intent is requesting to view recent calls
- * @return true if the intent is due to hitting the green send key while in a call
- */
- private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) {
- // If there is a call in progress go to the call screen
- if (recentCallsRequest) {
- final boolean callKey = intent.getBooleanExtra("call_key", false);
-
- try {
- ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
- if (callKey && phone != null && phone.showCallScreen()) {
- return true;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to handle send while in call", e);
- }
- }
-
- return false;
- }
-
- /**
- * Sets the current tab based on the intent's request type
- *
- * @param intent Intent that contains information about which tab should be selected
- */
- private void setCurrentTab(Intent intent) {
- // If we got here by hitting send and we're in call forward along to the in-call activity
- final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
- if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
- finish();
- return;
- }
-
- // Dismiss menu provided by any children activities
- Activity activity = getLocalActivityManager().
- getActivity(mTabHost.getCurrentTabTag());
- if (activity != null) {
- activity.closeOptionsMenu();
- }
-
- // Tell the children activities that they should ignore any possible saved
- // state and instead reload their state from the parent's intent
- intent.putExtra(EXTRA_IGNORE_STATE, true);
-
- // Remember the old manually selected tab index so that it can be restored if it is
- // overwritten by one of the programmatic tab selections
- final int savedTabIndex = mLastManuallySelectedTab;
-
- // Choose the tab based on the inbound intent
- if (intent.getBooleanExtra(ContactsFrontDoor.EXTRA_FRONT_DOOR, false)) {
- // Launched through the contacts front door, set the proper contacts tab (sticky
- // between favorites and contacts)
- SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
- boolean favoritesAsContacts = prefs.getBoolean(PREF_FAVORITES_AS_CONTACTS,
- PREF_FAVORITES_AS_CONTACTS_DEFAULT);
- if (favoritesAsContacts) {
- mTabHost.setCurrentTab(TAB_INDEX_FAVORITES);
- } else {
- mTabHost.setCurrentTab(TAB_INDEX_CONTACTS);
- }
- } else {
- // Not launched through the front door, look at the component to determine the tab
- String componentName = intent.getComponent().getClassName();
- if (getClass().getName().equals(componentName)) {
- if (recentCallsRequest) {
- mTabHost.setCurrentTab(TAB_INDEX_CALL_LOG);
- } else {
- mTabHost.setCurrentTab(TAB_INDEX_DIALER);
- }
- } else {
- mTabHost.setCurrentTab(mLastManuallySelectedTab);
- }
- }
-
- // Restore to the previous manual selection
- mLastManuallySelectedTab = savedTabIndex;
-
- // Tell the children activities that they should honor their saved states
- // instead of the state from the parent's intent
- intent.putExtra(EXTRA_IGNORE_STATE, false);
- }
-
- @Override
- public void onNewIntent(Intent newIntent) {
- setIntent(newIntent);
- fixIntent(newIntent);
- setCurrentTab(newIntent);
- final String action = newIntent.getAction();
- if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
- setupFilterText(newIntent);
- } else if (isDialIntent(newIntent)) {
- setupDialUri(newIntent);
- }
- }
-
- /** Returns true if the given intent contains a phone number to populate the dialer with */
- private boolean isDialIntent(Intent intent) {
- final String action = intent.getAction();
- if (Intent.ACTION_DIAL.equals(action)) {
- return true;
- }
- if (Intent.ACTION_VIEW.equals(action)) {
- final Uri data = intent.getData();
- if (data != null && "tel".equals(data.getScheme())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
- * This text originally came from a FILTER_CONTACTS_ACTION intent received
- * by this activity. The stored text will then be cleared after after this
- * method returns.
- *
- * @return The stored filter text
- */
- public String getAndClearFilterText() {
- String filterText = mFilterText;
- mFilterText = null;
- return filterText;
- }
-
- /**
- * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
- * This is so child activities can check if they are supposed to display a filter.
- *
- * @param intent The intent received in {@link #onNewIntent(Intent)}
- */
- private void setupFilterText(Intent intent) {
- // If the intent was relaunched from history, don't apply the filter text.
- if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
- return;
- }
- String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
- if (filter != null && filter.length() > 0) {
- mFilterText = filter;
- }
- }
-
- /**
- * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
- * originally came from a dial intent received by this activity. The stored
- * uri will then be cleared after after this method returns.
- *
- * @return The stored uri
- */
- public Uri getAndClearDialUri() {
- Uri dialUri = mDialUri;
- mDialUri = null;
- return dialUri;
- }
-
- /**
- * Stores the uri associated with a dial intent. This is so child activities can
- * check if they are supposed to display new dial info.
- *
- * @param intent The intent received in {@link #onNewIntent(Intent)}
- */
- private void setupDialUri(Intent intent) {
- // If the intent was relaunched from history, don't reapply the intent.
- if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
- return;
- }
- mDialUri = intent.getData();
- }
-
- @Override
- public void onBackPressed() {
- if (isTaskRoot()) {
- // 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 {
- super.onBackPressed();
- }
- }
-
- /** {@inheritDoc} */
- public void onTabChanged(String tabId) {
- // Because we're using Activities as our tab children, we trigger
- // onWindowFocusChanged() to let them know when they're active. This may
- // seem to duplicate the purpose of onResume(), but it's needed because
- // onResume() can't reliably check if a keyguard is active.
- Activity activity = getLocalActivityManager().getActivity(tabId);
- if (activity != null) {
- activity.onWindowFocusChanged(true);
- }
-
- // Remember this tab index. This function is also called, if the tab is set automatically
- // in which case the setter (setCurrentTab) has to set this to its old value afterwards
- mLastManuallySelectedTab = mTabHost.getCurrentTab();
- }
-}
diff --git a/src/com/android/contacts/SpecialCharSequenceMgr.java b/src/com/android/contacts/SpecialCharSequenceMgr.java
index a047a68..9f9f40d 100644
--- a/src/com/android/contacts/SpecialCharSequenceMgr.java
+++ b/src/com/android/contacts/SpecialCharSequenceMgr.java
@@ -54,7 +54,7 @@
private SpecialCharSequenceMgr() {
}
- static boolean handleChars(Context context, String input, EditText textField) {
+ public static boolean handleChars(Context context, String input, EditText textField) {
return handleChars(context, input, false, textField);
}
diff --git a/src/com/android/contacts/TypePrecedence.java b/src/com/android/contacts/TypePrecedence.java
index 2adf3b5..e89c5aa 100644
--- a/src/com/android/contacts/TypePrecedence.java
+++ b/src/com/android/contacts/TypePrecedence.java
@@ -42,6 +42,7 @@
//TODO These may need to be tweaked.
private static final int[] TYPE_PRECEDENCE_PHONES = {
Phone.TYPE_CUSTOM,
+ Phone.TYPE_MAIN,
Phone.TYPE_MOBILE,
Phone.TYPE_HOME,
Phone.TYPE_WORK,
diff --git a/src/com/android/contacts/activities/CallLogActivity.java b/src/com/android/contacts/activities/CallLogActivity.java
new file mode 100644
index 0000000..13c3209
--- /dev/null
+++ b/src/com/android/contacts/activities/CallLogActivity.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.ContactsSearchManager;
+import com.android.contacts.R;
+import com.android.contacts.calllog.CallLogFragment;
+import com.android.internal.telephony.ITelephony;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * Displays a list of call log entries.
+ */
+public class CallLogActivity extends Activity {
+ private static final String TAG = "CallLogActivity";
+
+ private CallLogFragment mFragment;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+
+ setContentView(R.layout.call_log_activity);
+
+ // Typing here goes to the dialer
+ setDefaultKeyMode(DEFAULT_KEYS_DIALER);
+
+ mFragment = (CallLogFragment) getFragmentManager().findFragmentById(
+ R.id.call_log_fragment);
+ }
+
+ public CallLogFragment getFragment() {
+ return mFragment;
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ super.onWindowFocusChanged(hasFocus);
+
+ // Clear notifications only when window gains focus. This activity won't
+ // immediately receive focus if the keyguard screen is above it.
+ if (hasFocus) {
+ try {
+ ITelephony telephony =
+ ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
+ if (telephony != null) {
+ telephony.cancelMissedCallsNotification();
+ } else {
+ Log.w(TAG, "Telephony service is null, can't call " +
+ "cancelMissedCallsNotification");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
+ }
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_CALL: {
+ long callPressDiff = SystemClock.uptimeMillis() - event.getDownTime();
+ if (callPressDiff >= ViewConfiguration.getLongPressTimeout()) {
+ // Launch voice dialer
+ Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ }
+ return true;
+ }
+ }
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_CALL:
+ try {
+ ITelephony phone = ITelephony.Stub.asInterface(
+ ServiceManager.checkService("phone"));
+ if (phone != null && !phone.isIdle()) {
+ // Let the super class handle it
+ break;
+ }
+ } catch (RemoteException re) {
+ // Fall through and try to call the contact
+ }
+
+ mFragment.callSelectedEntry();
+ return true;
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
+ boolean globalSearch) {
+ if (globalSearch) {
+ super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
+ } else {
+ ContactsSearchManager.startSearch(this, initialQuery);
+ }
+ }
+}
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 56e8353..17e05c7 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -22,6 +22,7 @@
import com.android.contacts.R;
import com.android.contacts.detail.ContactDetailFragment;
import com.android.contacts.interactions.ContactDeletionInteraction;
+import com.android.contacts.util.PhoneCapabilityTester;
import android.accounts.Account;
import android.content.ActivityNotFoundException;
@@ -44,6 +45,23 @@
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
+ if (PhoneCapabilityTester.isUsingTwoPanes(this)) {
+ // This activity must not be shown. We have to select the contact in the
+ // ContactBrowserActivity instead ==> Create a forward intent and finish
+ final Intent originalIntent = getIntent();
+ Intent intent = new Intent();
+ intent.setAction(originalIntent.getAction());
+ intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
+ intent.setFlags(
+ Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_FORWARD_RESULT
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+
+ intent.setClass(this, PeopleActivity.class);
+ startActivity(intent);
+ finish();
+ return;
+ }
+
setContentView(R.layout.contact_detail_activity);
mFragment = (ContactDetailFragment) getFragmentManager().findFragmentById(
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 35f7413..cc0be9d 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -53,8 +53,6 @@
public static final String ACTION_SAVE_COMPLETED = "saveCompleted";
private ContactEditorFragment mFragment;
- private Button mDoneButton;
- private Button mRevertButton;
private DialogManager mDialogManager = new DialogManager(this);
@@ -90,22 +88,6 @@
mFragment.setListener(mFragmentListener);
Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
mFragment.load(action, uri, getIntent().getExtras());
-
- // Depending on the use-case, this activity has Done and Revert buttons or not.
- mDoneButton = (Button) findViewById(R.id.done);
- mRevertButton = (Button) findViewById(R.id.revert);
- if (mDoneButton != null) mDoneButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mFragment.save(SaveMode.CLOSE);
- }
- });
- if (mRevertButton != null) mRevertButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- finish();
- }
- });
}
@Override
@@ -174,8 +156,7 @@
public void onSaveFinished(int resultCode, Intent resultIntent, boolean navigateHome) {
setResult(resultCode, resultIntent);
if (navigateHome) {
- Intent intent = new Intent(ContactEditorActivity.this,
- ContactBrowserActivity.class);
+ Intent intent = new Intent(ContactEditorActivity.this, PeopleActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
@@ -188,11 +169,6 @@
}
@Override
- public void onAccountSelectorAborted() {
- finish();
- }
-
- @Override
public void onContactNotFound() {
setResult(Activity.RESULT_CANCELED, null);
finish();
diff --git a/src/com/android/contacts/activities/ContactSelectionActivity.java b/src/com/android/contacts/activities/ContactSelectionActivity.java
index 4efc43f..c255ba1 100644
--- a/src/com/android/contacts/activities/ContactSelectionActivity.java
+++ b/src/com/android/contacts/activities/ContactSelectionActivity.java
@@ -23,7 +23,9 @@
import com.android.contacts.list.ContactsIntentResolver;
import com.android.contacts.list.ContactsRequest;
import com.android.contacts.list.DirectoryListLoader;
+import com.android.contacts.list.EmailAddressPickerFragment;
import com.android.contacts.list.OnContactPickerActionListener;
+import com.android.contacts.list.OnEmailAddressPickerActionListener;
import com.android.contacts.list.OnPhoneNumberPickerActionListener;
import com.android.contacts.list.OnPostalAddressPickerActionListener;
import com.android.contacts.list.PhoneNumberPickerFragment;
@@ -171,6 +173,11 @@
break;
}
+ case ContactsRequest.ACTION_PICK_EMAIL: {
+ setTitle(R.string.contactPickerActivityTitle);
+ break;
+ }
+
case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
setTitle(R.string.callShortcutActivityTitle);
break;
@@ -236,6 +243,11 @@
break;
}
+ case ContactsRequest.ACTION_PICK_EMAIL: {
+ mListFragment = new EmailAddressPickerFragment();
+ break;
+ }
+
case ContactsRequest.ACTION_CREATE_SHORTCUT_CALL: {
PhoneNumberPickerFragment fragment = new PhoneNumberPickerFragment();
fragment.setShortcutAction(Intent.ACTION_CALL);
@@ -284,6 +296,9 @@
} else if (mListFragment instanceof PostalAddressPickerFragment) {
((PostalAddressPickerFragment) mListFragment).setOnPostalAddressPickerActionListener(
new PostalAddressPickerActionListener());
+ } else if (mListFragment instanceof EmailAddressPickerFragment) {
+ ((EmailAddressPickerFragment) mListFragment).setOnEmailAddressPickerActionListener(
+ new EmailAddressPickerActionListener());
} else {
throw new IllegalStateException("Unsupported list fragment type: " + mListFragment);
}
@@ -334,6 +349,14 @@
}
}
+ private final class EmailAddressPickerActionListener implements
+ OnEmailAddressPickerActionListener {
+ @Override
+ public void onPickEmailAddressAction(Uri dataUri) {
+ returnPickerResult(dataUri);
+ }
+ }
+
public void startActivityAndForwardResult(final Intent intent) {
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
diff --git a/src/com/android/contacts/activities/ContactsFrontDoor.java b/src/com/android/contacts/activities/ContactsFrontDoor.java
deleted file mode 100644
index 3677cce..0000000
--- a/src/com/android/contacts/activities/ContactsFrontDoor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.contacts.activities;
-
-import com.android.contacts.ContactsActivity;
-import com.android.contacts.DialtactsActivity;
-import com.android.contacts.util.PhoneCapabilityTester;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-public class ContactsFrontDoor extends ContactsActivity {
- public static final String EXTRA_FRONT_DOOR = "front_door";
-
- @Override
- public void onCreate(Bundle savedState) {
- super.onCreate(savedState);
-
- Intent originalIntent = getIntent();
- Intent intent = new Intent();
- intent.setAction(originalIntent.getAction());
- intent.setDataAndType(originalIntent.getData(), originalIntent.getType());
- intent.setFlags(
- Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_FORWARD_RESULT
- | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- intent.putExtra(EXTRA_FRONT_DOOR, true);
-
- if (PhoneCapabilityTester.isPhone(this)) {
- // Default to the normal dialtacts layout
- intent.setClass(this, DialtactsActivity.class);
- } else {
- // No tabs, just a contact list
- intent.setClass(this, ContactBrowserActivity.class);
- }
-
- startActivity(intent);
- finish();
- }
-}
diff --git a/src/com/android/contacts/activities/DialpadActivity.java b/src/com/android/contacts/activities/DialpadActivity.java
new file mode 100644
index 0000000..bb122df
--- /dev/null
+++ b/src/com/android/contacts/activities/DialpadActivity.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.ContactsSearchManager;
+import com.android.contacts.R;
+import com.android.contacts.dialpad.DialpadFragment;
+
+import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.ViewConfiguration;
+import android.view.Window;
+import android.view.inputmethod.InputMethodManager;
+
+/**
+ * Activity that displays a twelve-key phone dialpad.
+ * This is just a simple container around DialpadFragment.
+ * @see DialpadFragment
+ */
+public class DialpadActivity extends Activity {
+ private static final String TAG = "DialpadActivity";
+
+ private DialpadFragment mFragment;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.dialpad_activity);
+
+ Resources r = getResources();
+ // Do not show title in the case the device is in carmode.
+ if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK) ==
+ Configuration.UI_MODE_TYPE_CAR) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ }
+
+ mFragment = (DialpadFragment) getFragmentManager().findFragmentById(
+ R.id.dialpad_fragment);
+
+ // Manually run the onRestoreInstanceState() sequence here, but only if
+ // our intent does *not* have the DialtactsActivity.EXTRA_IGNORE_STATE
+ // set (see the references to EXTRA_IGNORE_STATE in DialtactsActivity).
+ // TODO: Find a cleaner way of doing this.
+ if (!mFragment.resolveIntent() && (icicle != null)) {
+ super.onRestoreInstanceState(icicle);
+ }
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle icicle) {
+ // Do nothing, state is restored in onCreate() if needed
+ }
+
+ @Override
+ protected void onNewIntent(Intent newIntent) {
+ setIntent(newIntent);
+ mFragment.resolveIntent();
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ // Pass this lifecycle event down to the fragment
+ mFragment.onPostCreate();
+ }
+
+ public DialpadFragment getFragment() {
+ return mFragment;
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ if (hasFocus) {
+ // Hide soft keyboard, if visible (it's fugly over button dialer).
+ // The only known case where this will be true is when launching the dialer with
+ // ACTION_DIAL via a soft keyboard. we dismiss it here because we don't
+ // have a window token yet in onCreate / onNewIntent
+ InputMethodManager inputMethodManager = (InputMethodManager)
+ getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(
+ mFragment.getDigitsWidget().getWindowToken(), 0);
+ }
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_CALL: {
+ long callPressDiff = SystemClock.uptimeMillis() - event.getDownTime();
+ if (callPressDiff >= ViewConfiguration.getLongPressTimeout()) {
+ // Launch voice dialer
+ Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, "Failed to launch voice dialer: " + e);
+ }
+ }
+ return true;
+ }
+ case KeyEvent.KEYCODE_1: {
+ long timeDiff = SystemClock.uptimeMillis() - event.getDownTime();
+ if (timeDiff >= ViewConfiguration.getLongPressTimeout()) {
+ // Long press detected, call voice mail
+ mFragment.callVoicemail();
+ }
+ return true;
+ }
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_CALL: {
+ mFragment.dialButtonPressed();
+ return true;
+ }
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
+ boolean globalSearch) {
+ if (globalSearch) {
+ super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
+ } else {
+ ContactsSearchManager.startSearch(this, initialQuery);
+ }
+ }
+}
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
new file mode 100644
index 0000000..a0d77ab
--- /dev/null
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -0,0 +1,561 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.R;
+import com.android.contacts.calllog.CallLogFragment;
+import com.android.contacts.dialpad.DialpadFragment;
+import com.android.contacts.interactions.ImportExportDialogFragment;
+import com.android.contacts.interactions.PhoneNumberInteraction;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contacts.list.ContactsIntentResolver;
+import com.android.contacts.list.ContactsRequest;
+import com.android.contacts.list.DefaultContactBrowseListFragment;
+import com.android.contacts.list.DirectoryListLoader;
+import com.android.contacts.list.OnContactBrowserActionListener;
+import com.android.contacts.list.StrequentContactListFragment;
+import com.android.contacts.preference.ContactsPreferenceActivity;
+import com.android.internal.telephony.ITelephony;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.CallLog.Calls;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents.UI;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+
+/**
+ * The dialer activity that has one tab with the virtual 12key
+ * dialer, a tab with recent calls in it, a tab with the contacts and
+ * a tab with the favorite. This is the container and the tabs are
+ * embedded using intents.
+ * The dialer tab's title is 'phone', a more common name (see strings.xml).
+ */
+public class DialtactsActivity extends Activity {
+ private static final String TAG = "DialtactsActivity";
+
+ private static final int TAB_INDEX_DIALER = 0;
+ private static final int TAB_INDEX_CALL_LOG = 1;
+ private static final int TAB_INDEX_CONTACTS = 2;
+ private static final int TAB_INDEX_FAVORITES = 3;
+
+ public static final String EXTRA_IGNORE_STATE = "ignore-state";
+
+ /** Name of the dialtacts shared preferences */
+ static final String PREFS_DIALTACTS = "dialtacts";
+ /** If true, when handling the contacts intent the favorites tab will be shown instead */
+ static final String PREF_FAVORITES_AS_CONTACTS = "favorites_as_contacts";
+ static final boolean PREF_FAVORITES_AS_CONTACTS_DEFAULT = false;
+
+ /** Last manually selected tab index */
+ private static final String PREF_LAST_MANUALLY_SELECTED_TAB = "last_manually_selected_tab";
+ private static final int PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT = TAB_INDEX_DIALER;
+
+ private String mFilterText;
+ private Uri mDialUri;
+ private DialpadFragment mDialpadFragment;
+ private CallLogFragment mCallLogFragment;
+ private DefaultContactBrowseListFragment mContactsFragment;
+ private StrequentContactListFragment mStrequentFragment;
+
+ /**
+ * The index of the tab that has last been manually selected (the user clicked on a tab).
+ * This value does not keep track of programmatically set Tabs (e.g. Call Log after a Call)
+ */
+ private int mLastManuallySelectedTab;
+
+ // TODO: It would be great to eventually remove all interactions and replace by DialogFragments
+ private PhoneNumberInteraction mPhoneNumberCallInteraction;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ final Intent intent = getIntent();
+ fixIntent(intent);
+
+ setContentView(R.layout.dialtacts_activity);
+
+ final FragmentManager fragmentManager = getFragmentManager();
+ mDialpadFragment = (DialpadFragment) fragmentManager
+ .findFragmentById(R.id.dialpad_fragment);
+ mCallLogFragment = (CallLogFragment) fragmentManager
+ .findFragmentById(R.id.call_log_fragment);
+ mContactsFragment = (DefaultContactBrowseListFragment) fragmentManager
+ .findFragmentById(R.id.contacts_fragment);
+ mStrequentFragment = (StrequentContactListFragment) fragmentManager
+ .findFragmentById(R.id.favorites_fragment);
+
+ // Hide all tabs (the current tab will later be reshown once a tab is selected)
+ final FragmentTransaction transaction = fragmentManager.beginTransaction();
+ transaction.hide(mDialpadFragment);
+ transaction.hide(mCallLogFragment);
+ transaction.hide(mContactsFragment);
+ transaction.hide(mStrequentFragment);
+ transaction.commit();
+
+ // Setup the ActionBar tabs (the order matches the tab-index contants TAB_INDEX_*)
+ setupDialer();
+ setupCallLog();
+ setupContacts();
+ setupFavorites();
+ getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+ getActionBar().setDisplayShowTitleEnabled(false);
+ getActionBar().setDisplayShowHomeEnabled(false);
+
+ // Load the last manually loaded tab
+ final SharedPreferences prefs = getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE);
+ mLastManuallySelectedTab = prefs.getInt(PREF_LAST_MANUALLY_SELECTED_TAB,
+ PREF_LAST_MANUALLY_SELECTED_TAB_DEFAULT);
+
+ setCurrentTab(intent);
+
+ if (UI.FILTER_CONTACTS_ACTION.equals(intent.getAction())
+ && icicle == null) {
+ setupFilterText(intent);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ final int currentTabIndex = getActionBar().getSelectedTab().getPosition();
+ final SharedPreferences.Editor editor =
+ getSharedPreferences(PREFS_DIALTACTS, MODE_PRIVATE).edit();
+ if (currentTabIndex == TAB_INDEX_CONTACTS || currentTabIndex == TAB_INDEX_FAVORITES) {
+ editor.putBoolean(PREF_FAVORITES_AS_CONTACTS, currentTabIndex == TAB_INDEX_FAVORITES);
+ }
+ editor.putInt(PREF_LAST_MANUALLY_SELECTED_TAB, mLastManuallySelectedTab);
+
+ editor.apply();
+ }
+
+ private void fixIntent(Intent intent) {
+ // This should be cleaned up: the call key used to send an Intent
+ // that just said to go to the recent calls list. It now sends this
+ // abstract action, but this class hasn't been rewritten to deal with it.
+ if (Intent.ACTION_CALL_BUTTON.equals(intent.getAction())) {
+ intent.setDataAndType(Calls.CONTENT_URI, Calls.CONTENT_TYPE);
+ intent.putExtra("call_key", true);
+ setIntent(intent);
+ }
+ }
+
+ private void setupDialer() {
+ final Tab tab = getActionBar().newTab();
+ // TODO: Temporarily disable tab text labels (in all 4 tabs in this
+ // activity) so that the current tabs will all fit onscreen in
+ // portrait (bug 4520620). (Also note we do setText("") rather
+ // leaving the text null, to work around bug 4521549.)
+ tab.setText(""); // R.string.dialerIconLabel
+ tab.setTabListener(new TabChangeListener(mDialpadFragment));
+ tab.setIcon(R.drawable.ic_tab_dialer);
+ getActionBar().addTab(tab);
+ mDialpadFragment.resolveIntent();
+ }
+
+ private void setupCallLog() {
+ final Tab tab = getActionBar().newTab();
+ tab.setText(""); // R.string.recentCallsIconLabel
+ tab.setIcon(R.drawable.ic_tab_recent);
+ tab.setTabListener(new TabChangeListener(mCallLogFragment));
+ getActionBar().addTab(tab);
+ }
+
+ private void setupContacts() {
+ final Tab tab = getActionBar().newTab();
+ tab.setText(""); // R.string.contactsIconLabel
+ tab.setIcon(R.drawable.ic_tab_contacts);
+ tab.setTabListener(new TabChangeListener(mContactsFragment));
+ getActionBar().addTab(tab);
+
+ // TODO: We should not artificially create Intents and put them into the Fragment.
+ // It would be nicer to directly pass in the UI constant
+ Intent intent = new Intent(UI.LIST_ALL_CONTACTS_ACTION);
+ intent.setClass(this, PeopleActivity.class);
+
+ ContactsIntentResolver resolver = new ContactsIntentResolver(this);
+ ContactsRequest request = resolver.resolveIntent(intent);
+ final ContactListFilter filter = new ContactListFilter(
+ ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS);
+ mContactsFragment.setFilter(filter, false);
+ mContactsFragment.setSearchMode(request.isSearchMode());
+ mContactsFragment.setQueryString(request.getQueryString(), false);
+ mContactsFragment.setContactsRequest(request);
+ mContactsFragment.setDirectorySearchMode(request.isDirectorySearchEnabled()
+ ? DirectoryListLoader.SEARCH_MODE_DEFAULT
+ : DirectoryListLoader.SEARCH_MODE_NONE);
+ mContactsFragment.setOnContactListActionListener(mListFragmentListener);
+ }
+
+ private void setupFavorites() {
+ final Tab tab = getActionBar().newTab();
+ tab.setText(""); // R.string.contactsFavoritesLabel
+ tab.setIcon(R.drawable.ic_tab_starred);
+ tab.setTabListener(new TabChangeListener(mStrequentFragment));
+ getActionBar().addTab(tab);
+
+ // TODO: We should not artificially create Intents and put them into the Fragment.
+ // It would be nicer to directly pass in the UI constant
+ Intent intent = new Intent(UI.LIST_STREQUENT_ACTION);
+ intent.setClass(this, PeopleActivity.class);
+
+ ContactsIntentResolver resolver = new ContactsIntentResolver(this);
+ ContactsRequest request = resolver.resolveIntent(intent);
+ final ContactListFilter filter = new ContactListFilter(
+ ContactListFilter.FILTER_TYPE_STARRED);
+ mStrequentFragment.setFilter(filter, false);
+ mStrequentFragment.setSearchMode(request.isSearchMode());
+ mStrequentFragment.setQueryString(request.getQueryString(), false);
+ mStrequentFragment.setContactsRequest(request);
+ mStrequentFragment.setDirectorySearchMode(request.isDirectorySearchEnabled()
+ ? DirectoryListLoader.SEARCH_MODE_DEFAULT
+ : DirectoryListLoader.SEARCH_MODE_NONE);
+ mStrequentFragment.setOnContactListActionListener(mListFragmentListener);
+ }
+
+ /**
+ * Returns true if the intent is due to hitting the green send key while in a call.
+ *
+ * @param intent the intent that launched this activity
+ * @param recentCallsRequest true if the intent is requesting to view recent calls
+ * @return true if the intent is due to hitting the green send key while in a call
+ */
+ private boolean isSendKeyWhileInCall(final Intent intent, final boolean recentCallsRequest) {
+ // If there is a call in progress go to the call screen
+ if (recentCallsRequest) {
+ final boolean callKey = intent.getBooleanExtra("call_key", false);
+
+ try {
+ ITelephony phone = ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
+ if (callKey && phone != null && phone.showCallScreen()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to handle send while in call", e);
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Sets the current tab based on the intent's request type
+ *
+ * @param intent Intent that contains information about which tab should be selected
+ */
+ private void setCurrentTab(Intent intent) {
+ // If we got here by hitting send and we're in call forward along to the in-call activity
+ final boolean recentCallsRequest = Calls.CONTENT_TYPE.equals(intent.getType());
+ if (isSendKeyWhileInCall(intent, recentCallsRequest)) {
+ finish();
+ return;
+ }
+
+ // Tell the children activities that they should ignore any possible saved
+ // state and instead reload their state from the parent's intent
+ intent.putExtra(EXTRA_IGNORE_STATE, true);
+
+ // Remember the old manually selected tab index so that it can be restored if it is
+ // overwritten by one of the programmatic tab selections
+ final int savedTabIndex = mLastManuallySelectedTab;
+
+ // Look at the component to determine the tab
+ String componentName = intent.getComponent().getClassName();
+ if (getClass().getName().equals(componentName)) {
+ if (recentCallsRequest) {
+ getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_CALL_LOG));
+ } else {
+ getActionBar().selectTab(getActionBar().getTabAt(TAB_INDEX_DIALER));
+ }
+ } else {
+ getActionBar().selectTab(getActionBar().getTabAt(mLastManuallySelectedTab));
+ }
+
+ // Restore to the previous manual selection
+ mLastManuallySelectedTab = savedTabIndex;
+
+ // Tell the children activities that they should honor their saved states
+ // instead of the state from the parent's intent
+ intent.putExtra(EXTRA_IGNORE_STATE, false);
+ }
+
+ @Override
+ public void onNewIntent(Intent newIntent) {
+ setIntent(newIntent);
+ fixIntent(newIntent);
+ setCurrentTab(newIntent);
+ final String action = newIntent.getAction();
+ if (UI.FILTER_CONTACTS_ACTION.equals(action)) {
+ setupFilterText(newIntent);
+ } else if (isDialIntent(newIntent)) {
+ setupDialUri(newIntent);
+ }
+ }
+
+ /** Returns true if the given intent contains a phone number to populate the dialer with */
+ private boolean isDialIntent(Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_DIAL.equals(action)) {
+ return true;
+ }
+ if (Intent.ACTION_VIEW.equals(action)) {
+ final Uri data = intent.getData();
+ if (data != null && "tel".equals(data.getScheme())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Retrieves the filter text stored in {@link #setupFilterText(Intent)}.
+ * This text originally came from a FILTER_CONTACTS_ACTION intent received
+ * by this activity. The stored text will then be cleared after after this
+ * method returns.
+ *
+ * @return The stored filter text
+ */
+ public String getAndClearFilterText() {
+ String filterText = mFilterText;
+ mFilterText = null;
+ return filterText;
+ }
+
+ /**
+ * Stores the filter text associated with a FILTER_CONTACTS_ACTION intent.
+ * This is so child activities can check if they are supposed to display a filter.
+ *
+ * @param intent The intent received in {@link #onNewIntent(Intent)}
+ */
+ private void setupFilterText(Intent intent) {
+ // If the intent was relaunched from history, don't apply the filter text.
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
+ return;
+ }
+ String filter = intent.getStringExtra(UI.FILTER_TEXT_EXTRA_KEY);
+ if (filter != null && filter.length() > 0) {
+ mFilterText = filter;
+ }
+ }
+
+ /**
+ * Retrieves the uri stored in {@link #setupDialUri(Intent)}. This uri
+ * originally came from a dial intent received by this activity. The stored
+ * uri will then be cleared after after this method returns.
+ *
+ * @return The stored uri
+ */
+ public Uri getAndClearDialUri() {
+ Uri dialUri = mDialUri;
+ mDialUri = null;
+ return dialUri;
+ }
+
+ /**
+ * Stores the uri associated with a dial intent. This is so child activities can
+ * check if they are supposed to display new dial info.
+ *
+ * @param intent The intent received in {@link #onNewIntent(Intent)}
+ */
+ private void setupDialUri(Intent intent) {
+ // If the intent was relaunched from history, don't reapply the intent.
+ if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
+ return;
+ }
+ mDialUri = intent.getData();
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (isTaskRoot()) {
+ // 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 {
+ super.onBackPressed();
+ }
+ }
+
+ private PhoneNumberInteraction getPhoneNumberCallInteraction() {
+ if (mPhoneNumberCallInteraction == null) {
+ mPhoneNumberCallInteraction = new PhoneNumberInteraction(this, false, null);
+ }
+ return mPhoneNumberCallInteraction;
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ // Pass this lifecycle event down to the fragment
+ mDialpadFragment.onPostCreate();
+ }
+
+ /**
+ * Tab change listener that is instantiated once for each tab. Handles showing/hiding tabs
+ * and remembers manual tab selections
+ */
+ private class TabChangeListener implements TabListener {
+ private final Fragment mFragment;
+
+ public TabChangeListener(Fragment fragment) {
+ mFragment = fragment;
+ }
+
+ @Override
+ public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+ ft.hide(mFragment);
+ }
+
+ @Override
+ public void onTabSelected(Tab tab, FragmentTransaction ft) {
+ ft.show(mFragment);
+
+ // Remember this tab index. This function is also called, if the tab is set
+ // automatically in which case the setter (setCurrentTab) has to set this to its old
+ // value afterwards
+ mLastManuallySelectedTab = tab.getPosition();
+ }
+
+ @Override
+ public void onTabReselected(Tab tab, FragmentTransaction ft) {
+ }
+ }
+
+ private OnContactBrowserActionListener mListFragmentListener =
+ new OnContactBrowserActionListener() {
+ @Override
+ public void onViewContactAction(Uri contactLookupUri) {
+ startActivity(new Intent(Intent.ACTION_VIEW, contactLookupUri));
+ }
+
+ @Override
+ public void onSmsContactAction(Uri contactUri) {
+ }
+
+ @Override
+ public void onSelectionChange() {
+ }
+
+ @Override
+ public void onRemoveFromFavoritesAction(Uri contactUri) {
+ }
+
+ @Override
+ public void onInvalidSelection() {
+ }
+
+ @Override
+ public void onFinishAction() {
+ }
+
+ @Override
+ public void onEditContactAction(Uri contactLookupUri) {
+ }
+
+ @Override
+ public void onDeleteContactAction(Uri contactUri) {
+ }
+
+ @Override
+ public void onCreateNewContactAction() {
+ }
+
+ @Override
+ public void onCallContactAction(Uri contactUri) {
+ getPhoneNumberCallInteraction().startInteraction(contactUri);
+ }
+
+ @Override
+ public void onAddToFavoritesAction(Uri contactUri) {
+ }
+ };
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // For now, create the menu in here. It would be nice to do this in the Fragment,
+ // but that Fragment is re-used in other views.
+ final ActionBar actionBar = getActionBar();
+ if (actionBar == null) return false;
+ final Tab tab = actionBar.getSelectedTab();
+ if (tab == null) return false;
+ final int tabIndex = tab.getPosition();
+ if (tabIndex != TAB_INDEX_CONTACTS && tabIndex != TAB_INDEX_FAVORITES) return false;
+
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.list, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // This is currently a copy of the equivalent code of ContactBrowserActivity (with the
+ // exception of menu_add, because we do not select items in the list).
+ // Should be consolidated
+ switch (item.getItemId()) {
+ case R.id.menu_settings: {
+ final Intent intent = new Intent(this, ContactsPreferenceActivity.class);
+ startActivity(intent);
+ return true;
+ }
+ case R.id.menu_search: {
+ onSearchRequested();
+ return true;
+ }
+ case R.id.menu_add: {
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ startActivity(intent);
+ return true;
+ }
+ case R.id.menu_import_export: {
+ ImportExportDialogFragment.show(getFragmentManager());
+ return true;
+ }
+ case R.id.menu_accounts: {
+ final Intent intent = new Intent(Settings.ACTION_SYNC_SETTINGS);
+ intent.putExtra(Settings.EXTRA_AUTHORITIES, new String[] {
+ ContactsContract.AUTHORITY
+ });
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ startActivity(intent);
+ return true;
+ }
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+}
diff --git a/src/com/android/contacts/activities/GroupBrowserActivity.java b/src/com/android/contacts/activities/GroupBrowserActivity.java
new file mode 100644
index 0000000..e8b3ad8
--- /dev/null
+++ b/src/com/android/contacts/activities/GroupBrowserActivity.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Displays a list to browse groups.
+ */
+public class GroupBrowserActivity extends ContactsActivity {
+
+ private static final String TAG = "GroupBrowserActivity";
+
+ public GroupBrowserActivity() {
+ }
+
+ @Override
+ protected void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+ configureContentView(true, savedState);
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ setIntent(intent);
+ configureContentView(false, null);
+ }
+
+ private void configureContentView(boolean createContentView, Bundle savedState) {
+ // TODO: Create Intent Resolver to handle the different ways users can get to this list.
+ // TODO: Use savedState if necessary
+ // TODO: Setup action bar
+ if (createContentView) {
+ setContentView(R.layout.group_browser_activity);
+ }
+ }
+}
diff --git a/src/com/android/contacts/activities/GroupDetailActivity.java b/src/com/android/contacts/activities/GroupDetailActivity.java
new file mode 100644
index 0000000..edc460c
--- /dev/null
+++ b/src/com/android/contacts/activities/GroupDetailActivity.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.ContactsActivity;
+import com.android.contacts.R;
+
+import android.os.Bundle;
+
+public class GroupDetailActivity extends ContactsActivity {
+
+ private static final String TAG = "GroupDetailActivity";
+
+ public static final String KEY_ACCOUNT_TYPE = "accountType";
+ public static final String KEY_ACCOUNT_NAME = "accountName";
+ public static final String KEY_GROUP_ID = "groupId";
+ public static final String KEY_GROUP_SOURCE_ID = "groupSourceId";
+ public static final String KEY_GROUP_READ_ONLY = "groupReadOnly";
+ public static final String KEY_GROUP_TITLE = "title";
+
+ @Override
+ public void onCreate(Bundle savedState) {
+ super.onCreate(savedState);
+
+ // TODO: Create Intent Resolver to handle the different ways users can get to this list.
+ // TODO: Handle search or key down
+
+ setContentView(R.layout.group_detail_activity);
+ }
+}
diff --git a/src/com/android/contacts/activities/ContactBrowserActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
similarity index 85%
rename from src/com/android/contacts/activities/ContactBrowserActivity.java
rename to src/com/android/contacts/activities/PeopleActivity.java
index f58a28c..1379e08 100644
--- a/src/com/android/contacts/activities/ContactBrowserActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -23,7 +23,7 @@
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.interactions.GroupDeletionDialogFragment;
import com.android.contacts.interactions.GroupRenamingDialogFragment;
-import com.android.contacts.interactions.ImportExportInteraction;
+import com.android.contacts.interactions.ImportExportDialogFragment;
import com.android.contacts.interactions.PhoneNumberInteraction;
import com.android.contacts.list.ContactBrowseListContextMenuAdapter;
import com.android.contacts.list.ContactBrowseListFragment;
@@ -42,7 +42,6 @@
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.preference.ContactsPreferenceActivity;
import com.android.contacts.util.AccountSelectionUtil;
-import com.android.contacts.util.AccountsListAdapter;
import com.android.contacts.util.DialogManager;
import com.android.contacts.widget.ContextMenuAdapter;
@@ -69,9 +68,6 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ListPopupWindow;
import android.widget.Toast;
import java.util.ArrayList;
@@ -80,7 +76,7 @@
* Displays a list to browse contacts. For xlarge screens, this also displays a detail-pane on
* the right.
*/
-public class ContactBrowserActivity extends ContactsActivity
+public class PeopleActivity extends ContactsActivity
implements View.OnCreateContextMenuListener, ActionBarAdapter.Listener,
DialogManager.DialogShowingViewActivity,
ContactListFilterController.ContactListFilterListener, ProviderStatusListener {
@@ -88,9 +84,8 @@
private static final String TAG = "ContactBrowserActivity";
private static final int SUBACTIVITY_NEW_CONTACT = 2;
- private static final int SUBACTIVITY_SETTINGS = 3;
- private static final int SUBACTIVITY_EDIT_CONTACT = 4;
- private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 5;
+ private static final int SUBACTIVITY_EDIT_CONTACT = 3;
+ private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 4;
private static final String KEY_SEARCH_MODE = "searchMode";
@@ -105,13 +100,18 @@
private boolean mSearchMode;
private ContactBrowseListFragment mListFragment;
+
+ /**
+ * Whether we have a right-side contact pane for displaying contact info while browsing.
+ * Generally means "this is a tablet".
+ */
private boolean mContactContentDisplayed;
+
private ContactDetailFragment mDetailFragment;
private DetailFragmentListener mDetailFragmentListener = new DetailFragmentListener();
private PhoneNumberInteraction mPhoneNumberCallInteraction;
private PhoneNumberInteraction mSendTextMessageInteraction;
- private ImportExportInteraction mImportExportInteraction;
private boolean mSearchInitiated;
@@ -125,9 +125,8 @@
private boolean mOptionsMenuContactsAvailable;
private boolean mOptionsMenuGroupActionsEnabled;
- private boolean mOptionsMenuCustomFilterChangeable;
- public ContactBrowserActivity() {
+ public PeopleActivity() {
mIntentResolver = new ContactsIntentResolver(this);
mContactListFilterController = new ContactListFilterController(this);
mContactListFilterController.addListener(this);
@@ -163,6 +162,17 @@
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
+ mAddContactImageView = getLayoutInflater().inflate(
+ R.layout.add_contact_menu_item, null, false);
+ View item = mAddContactImageView.findViewById(R.id.menu_item);
+ item.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
+ }
+ });
+
configureContentView(true, savedState);
}
@@ -190,7 +200,7 @@
}
if (createContentView) {
- setContentView(R.layout.contact_browser);
+ setContentView(R.layout.people_activity);
}
if (mRequest.getActionCode() == ContactsRequest.ACTION_VIEW_CONTACT
@@ -205,13 +215,15 @@
setTitle(mRequest.getActivityTitle());
- mHasActionBar = getWindow().hasFeature(Window.FEATURE_ACTION_BAR);
- if (mHasActionBar) {
- ActionBar actionBar = getActionBar();
+ if (createContentView) {
+ mHasActionBar = getWindow().hasFeature(Window.FEATURE_ACTION_BAR);
+ if (mHasActionBar) {
+ ActionBar actionBar = getActionBar();
- mActionBarAdapter = new ActionBarAdapter(this);
- mActionBarAdapter.onCreate(savedState, mRequest, actionBar);
- mActionBarAdapter.setContactListFilterController(mContactListFilterController);
+ mActionBarAdapter = new ActionBarAdapter(this);
+ mActionBarAdapter.onCreate(savedState, mRequest, actionBar);
+ mActionBarAdapter.setContactListFilterController(mContactListFilterController);
+ }
}
configureFragments(savedState == null);
@@ -224,7 +236,6 @@
}
mOptionsMenuContactsAvailable = false;
- mOptionsMenuCustomFilterChangeable = false;
mOptionsMenuGroupActionsEnabled = false;
mProviderStatus = -1;
@@ -488,7 +499,7 @@
@Override
public void onDeleteContactAction(Uri contactUri) {
- ContactDeletionInteraction.start(ContactBrowserActivity.this, contactUri, false);
+ ContactDeletionInteraction.start(PeopleActivity.this, contactUri, false);
}
@Override
@@ -535,16 +546,16 @@
@Override
public void onDeleteRequested(Uri contactUri) {
- ContactDeletionInteraction.start(ContactBrowserActivity.this, contactUri, false);
+ ContactDeletionInteraction.start(PeopleActivity.this, contactUri, false);
}
@Override
public void onCreateRawContactRequested(ArrayList<ContentValues> values, Account account) {
- Toast.makeText(ContactBrowserActivity.this, R.string.toast_making_personal_copy,
+ Toast.makeText(PeopleActivity.this, R.string.toast_making_personal_copy,
Toast.LENGTH_LONG).show();
Intent serviceIntent = ContactSaveService.createNewRawContactIntent(
- ContactBrowserActivity.this, values, account,
- ContactBrowserActivity.class, Intent.ACTION_VIEW);
+ PeopleActivity.this, values, account,
+ PeopleActivity.class, Intent.ACTION_VIEW);
startService(serviceIntent);
}
}
@@ -568,7 +579,7 @@
@Override
public void onImportContactsFromFileAction() {
- AccountSelectionUtil.doImportFromSdCard(ContactBrowserActivity.this, null);
+ AccountSelectionUtil.doImportFromSdCard(PeopleActivity.this, null);
}
@Override
@@ -621,26 +632,11 @@
if (mHasActionBar) {
inflater.inflate(R.menu.actions, menu);
- // On narrow screens we specify a NEW contact button in the {@link ActionBar}, so that
- // it can be in the overflow menu. On wide screens, we use a custom view because we need
- // its location for anchoring the account-selector popup.
- // TODO: Take this hack out later when the account switcher in the contact editor is
- // present.
+ // Change add contact button to button with a custom view
final MenuItem addContact = menu.findItem(R.id.menu_add);
- if (addContact != null) {
- mAddContactImageView = getLayoutInflater().inflate(
- R.layout.add_contact_menu_item, null, false);
- View item = mAddContactImageView.findViewById(R.id.menu_item);
- item.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- createNewContact();
- }
- });
- addContact.setActionView(mAddContactImageView);
- }
+ addContact.setActionView(mAddContactImageView);
return true;
- } else if (mRequest.getActionCode() == ContactsRequest.ACTION_DEFAULT ||
+ } else if (mRequest.getActionCode() == ContactsRequest.ACTION_ALL_CONTACTS ||
mRequest.getActionCode() == ContactsRequest.ACTION_STREQUENT) {
inflater.inflate(R.menu.list, menu);
return true;
@@ -668,10 +664,6 @@
return true;
}
- if (mOptionsMenuCustomFilterChangeable != isCustomFilterChangeable()) {
- return true;
- }
-
if (mListFragment != null && mListFragment.isOptionsMenuChanged()) {
return true;
}
@@ -691,13 +683,8 @@
}
MenuItem settings = menu.findItem(R.id.menu_settings);
- settings.setVisible(!ContactsPreferenceActivity.isEmpty(this));
-
- mOptionsMenuCustomFilterChangeable = isCustomFilterChangeable();
-
- MenuItem displayGroups = menu.findItem(R.id.menu_display_groups);
- if (displayGroups != null) {
- displayGroups.setVisible(mOptionsMenuCustomFilterChangeable);
+ if (settings != null) {
+ settings.setVisible(!ContactsPreferenceActivity.isEmpty(this));
}
mOptionsMenuGroupActionsEnabled = areGroupActionsEnabled();
@@ -728,16 +715,12 @@
return groupActionsEnabled;
}
- public boolean isCustomFilterChangeable() {
- return mRequest != null && mRequest.getActionCode() == ContactsRequest.ACTION_DEFAULT;
- }
-
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_settings: {
final Intent intent = new Intent(this, ContactsPreferenceActivity.class);
- startActivityForResult(intent, SUBACTIVITY_SETTINGS);
+ startActivity(intent);
return true;
}
case R.id.menu_search: {
@@ -745,16 +728,12 @@
return true;
}
case R.id.menu_add: {
- createNewContact();
- return true;
- }
- case R.id.menu_new_contact: {
final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
return true;
}
case R.id.menu_import_export: {
- getImportExportInteraction().startInteraction();
+ ImportExportDialogFragment.show(getFragmentManager());
return true;
}
case R.id.menu_accounts: {
@@ -782,35 +761,6 @@
return false;
}
- private void createNewContact() {
- final ArrayList<Account> accounts =
- AccountTypeManager.getInstance(this).getAccounts(true);
- if (accounts.size() <= 1 || mAddContactImageView == null) {
- // No account to choose or no control to anchor the popup-menu to
- // ==> just go straight to the editor which will disambig if necessary
- final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
- return;
- }
-
- final ListPopupWindow popup = new ListPopupWindow(this, null);
- popup.setWidth(getResources().getDimensionPixelSize(R.dimen.account_selector_popup_width));
- popup.setAnchorView(mAddContactImageView);
- final AccountsListAdapter adapter = new AccountsListAdapter(this, true);
- popup.setAdapter(adapter);
- popup.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- popup.dismiss();
- final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
- intent.putExtra(Intents.Insert.ACCOUNT, adapter.getItem(position));
- startActivityForResult(intent, SUBACTIVITY_NEW_CONTACT);
- }
- });
- popup.setModal(true);
- popup.show();
- }
-
@Override
public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
boolean globalSearch) {
@@ -831,9 +781,6 @@
dialog = getSendTextMessageInteraction().onCreateDialog(id, bundle);
if (dialog != null) return dialog;
- dialog = getImportExportInteraction().onCreateDialog(id, bundle);
- if (dialog != null) return dialog;
-
return super.onCreateDialog(id, bundle);
}
@@ -862,16 +809,13 @@
case SUBACTIVITY_EDIT_CONTACT:
case SUBACTIVITY_NEW_CONTACT: {
- if (resultCode == RESULT_OK) {
+ if (resultCode == RESULT_OK && mContactContentDisplayed) {
mRequest.setActionCode(ContactsRequest.ACTION_VIEW_CONTACT);
mListFragment.reloadDataAndSetSelectedUri(data.getData());
}
break;
}
- case SUBACTIVITY_SETTINGS:
- break;
-
// TODO: Using the new startActivityWithResultFromFragment API this should not be needed
// anymore
case ContactEntryListFragment.ACTIVITY_REQUEST_CODE_PICKER:
@@ -919,8 +863,7 @@
default: {
// Bring up the search UI if the user starts typing
final int unicodeChar = event.getUnicodeChar();
-
- if (unicodeChar != 0) {
+ if (unicodeChar != 0 && !Character.isWhitespace(unicodeChar)) {
String query = new String(new int[]{ unicodeChar }, 0, 1);
if (mHasActionBar) {
if (!mActionBarAdapter.isSearchMode()) {
@@ -998,13 +941,6 @@
return mSendTextMessageInteraction;
}
- private ImportExportInteraction getImportExportInteraction() {
- if (mImportExportInteraction == null) {
- mImportExportInteraction = new ImportExportInteraction(this);
- }
- return mImportExportInteraction;
- }
-
@Override
public DialogManager getDialogManager() {
return mDialogManager;
diff --git a/src/com/android/contacts/activities/ShowOrCreateActivity.java b/src/com/android/contacts/activities/ShowOrCreateActivity.java
index 7341430..5e14db4 100755
--- a/src/com/android/contacts/activities/ShowOrCreateActivity.java
+++ b/src/com/android/contacts/activities/ShowOrCreateActivity.java
@@ -182,7 +182,7 @@
} else if (count > 1) {
// If more than one, show pick list
Intent listIntent = new Intent(Intent.ACTION_SEARCH);
- listIntent.setComponent(new ComponentName(this, ContactBrowserActivity.class));
+ listIntent.setComponent(new ComponentName(this, PeopleActivity.class));
listIntent.putExtras(mCreateExtras);
startActivity(listIntent);
finish();
diff --git a/src/com/android/contacts/RecentCallsListActivity.java b/src/com/android/contacts/calllog/CallLogFragment.java
similarity index 74%
rename from src/com/android/contacts/RecentCallsListActivity.java
rename to src/com/android/contacts/calllog/CallLogFragment.java
index 0a3c178..13d2e6c 100644
--- a/src/com/android/contacts/RecentCallsListActivity.java
+++ b/src/com/android/contacts/calllog/CallLogFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,23 +14,21 @@
* limitations under the License.
*/
-package com.android.contacts;
+package com.android.contacts.calllog;
import com.android.common.widget.GroupingListAdapter;
+import com.android.contacts.CallDetailActivity;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.ITelephony;
+import com.google.common.annotations.VisibleForTesting;
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.ListActivity;
-import android.content.ActivityNotFoundException;
+import android.app.ListFragment;
import android.content.AsyncQueryHandler;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.DialogInterface.OnClickListener;
import android.database.CharArrayBuffer;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabaseCorruptException;
@@ -43,9 +41,6 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -60,15 +55,14 @@
import android.text.format.DateUtils;
import android.util.Log;
import android.view.ContextMenu;
-import android.view.KeyEvent;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
-import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
@@ -81,65 +75,70 @@
/**
* Displays a list of call log entries.
*/
-public class RecentCallsListActivity extends ListActivity
+public class CallLogFragment extends ListFragment
implements View.OnCreateContextMenuListener {
- private static final String TAG = "RecentCallsList";
+ private static final String TAG = "CallLogFragment";
- /** The projection to use when querying the call log table */
- static final String[] CALL_LOG_PROJECTION = new String[] {
- Calls._ID,
- Calls.NUMBER,
- Calls.DATE,
- Calls.DURATION,
- Calls.TYPE,
- Calls.CACHED_NAME,
- Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL,
- Calls.COUNTRY_ISO};
+ /** The query for the call log table */
+ private static final class CallLogQuery {
+ public static final String[] _PROJECTION = new String[] {
+ Calls._ID,
+ Calls.NUMBER,
+ Calls.DATE,
+ Calls.DURATION,
+ Calls.TYPE,
+ Calls.CACHED_NAME,
+ Calls.CACHED_NUMBER_TYPE,
+ Calls.CACHED_NUMBER_LABEL,
+ Calls.COUNTRY_ISO};
- static final int ID_COLUMN_INDEX = 0;
- static final int NUMBER_COLUMN_INDEX = 1;
- static final int DATE_COLUMN_INDEX = 2;
- static final int DURATION_COLUMN_INDEX = 3;
- static final int CALL_TYPE_COLUMN_INDEX = 4;
- static final int CALLER_NAME_COLUMN_INDEX = 5;
- static final int CALLER_NUMBERTYPE_COLUMN_INDEX = 6;
- static final int CALLER_NUMBERLABEL_COLUMN_INDEX = 7;
- static final int COUNTRY_ISO_COLUMN_INDEX = 8;
+ public static final int ID = 0;
+ public static final int NUMBER = 1;
+ public static final int DATE = 2;
+ public static final int DURATION = 3;
+ public static final int CALL_TYPE = 4;
+ public static final int CALLER_NAME = 5;
+ public static final int CALLER_NUMBERTYPE = 6;
+ public static final int CALLER_NUMBERLABEL = 7;
+ public static final int COUNTRY_ISO = 8;
+ }
- /** The projection to use when querying the phones table */
- static final String[] PHONES_PROJECTION = new String[] {
- PhoneLookup._ID,
- PhoneLookup.DISPLAY_NAME,
- PhoneLookup.TYPE,
- PhoneLookup.LABEL,
- PhoneLookup.NUMBER,
- PhoneLookup.NORMALIZED_NUMBER};
+ /** The query to use for the phones table */
+ private static final class PhoneQuery {
+ public static final String[] _PROJECTION = new String[] {
+ PhoneLookup._ID,
+ PhoneLookup.DISPLAY_NAME,
+ PhoneLookup.TYPE,
+ PhoneLookup.LABEL,
+ PhoneLookup.NUMBER,
+ PhoneLookup.NORMALIZED_NUMBER};
- static final int PERSON_ID_COLUMN_INDEX = 0;
- static final int NAME_COLUMN_INDEX = 1;
- static final int PHONE_TYPE_COLUMN_INDEX = 2;
- static final int LABEL_COLUMN_INDEX = 3;
- static final int MATCHED_NUMBER_COLUMN_INDEX = 4;
- static final int NORMALIZED_NUMBER_COLUMN_INDEX = 5;
+ public static final int PERSON_ID = 0;
+ public static final int NAME = 1;
+ public static final int PHONE_TYPE = 2;
+ public static final int LABEL = 3;
+ public static final int MATCHED_NUMBER = 4;
+ public static final int NORMALIZED_NUMBER = 5;
+ }
- private static final int MENU_ITEM_DELETE = 1;
- private static final int MENU_ITEM_DELETE_ALL = 2;
- private static final int MENU_ITEM_VIEW_CONTACTS = 3;
+ private static final class MenuItems {
+ public static final int DELETE = 1;
+ }
+
+ private static final class OptionsMenuItems {
+ public static final int DELETE_ALL = 1;
+ }
private static final int QUERY_TOKEN = 53;
private static final int UPDATE_TOKEN = 54;
- private static final int DIALOG_CONFIRM_DELETE_ALL = 1;
-
- RecentCallsAdapter mAdapter;
+ private CallLogAdapter mAdapter;
private QueryHandler mQueryHandler;
- String mVoiceMailNumber;
+ private String mVoiceMailNumber;
private String mCurrentCountryIso;
-
private boolean mScrollToTop;
- static final class ContactInfo {
+ public static final class ContactInfo {
public long personId;
public String name;
public int type;
@@ -151,27 +150,33 @@
public static ContactInfo EMPTY = new ContactInfo();
}
- public static final class RecentCallsListItemViews {
- TextView line1View;
- TextView labelView;
- TextView numberView;
- TextView dateView;
- ImageView iconView;
- View callView;
- ImageView groupIndicator;
- TextView groupSize;
+ public static final class CallLogListItemViews {
+ public TextView line1View;
+ public TextView labelView;
+ public TextView numberView;
+ public TextView dateView;
+ public ImageView iconView;
+ /** The icon used to place a call to the contact. Only present for non-group entries. */
+ public View callView;
+ /** The icon used to expand and collapse an entry. Only present for group entries. */
+ public ImageView groupIndicator;
+ /**
+ * The text view containing the number of items in the group. Only present for group
+ * entries.
+ */
+ public TextView groupSize;
}
- static final class CallerInfoQuery {
- String number;
- int position;
- String name;
- int numberType;
- String numberLabel;
+ public static final class CallerInfoQuery {
+ public String number;
+ public int position;
+ public String name;
+ public int numberType;
+ public String numberLabel;
}
/** Adapter class to fill in data for the Call Log */
- final class RecentCallsAdapter extends GroupingListAdapter
+ public final class CallLogAdapter extends GroupingListAdapter
implements Runnable, ViewTreeObserver.OnPreDrawListener, View.OnClickListener {
HashMap<String,ContactInfo> mContactInfo;
private final LinkedList<CallerInfoQuery> mRequests;
@@ -183,8 +188,6 @@
private boolean mFirst;
private Thread mCallerIdThread;
- private CharSequence[] mLabelArray;
-
private Drawable mDrawableIncoming;
private Drawable mDrawableOutgoing;
private Drawable mDrawableMissed;
@@ -195,6 +198,7 @@
private CharArrayBuffer mBuffer1 = new CharArrayBuffer(128);
private CharArrayBuffer mBuffer2 = new CharArrayBuffer(128);
+ @Override
public void onClick(View view) {
String number = (String) view.getTag();
if (!TextUtils.isEmpty(number)) {
@@ -211,6 +215,7 @@
}
}
+ @Override
public boolean onPreDraw() {
if (mFirst) {
mHandler.sendEmptyMessageDelayed(START_THREAD, 1000);
@@ -233,8 +238,8 @@
}
};
- public RecentCallsAdapter() {
- super(RecentCallsListActivity.this);
+ public CallLogAdapter() {
+ super(getActivity());
mContactInfo = new HashMap<String,ContactInfo>();
mRequests = new LinkedList<CallerInfoQuery>();
@@ -246,7 +251,6 @@
R.drawable.ic_call_log_list_outgoing_call);
mDrawableMissed = getResources().getDrawable(
R.drawable.ic_call_log_list_missed_call);
- mLabelArray = getResources().getTextArray(com.android.internal.R.array.phoneTypes);
}
/**
@@ -307,7 +311,7 @@
values.put(Calls.CACHED_NUMBER_LABEL, ci.label);
try {
- RecentCallsListActivity.this.getContentResolver().update(Calls.CONTENT_URI, values,
+ getActivity().getContentResolver().update(Calls.CONTENT_URI, values,
Calls.NUMBER + "='" + ciq.number + "'", null);
} catch (SQLiteDiskIOException e) {
Log.w(TAG, "Exception while updating call info", e);
@@ -369,7 +373,7 @@
String[] selectionArgs = new String[] { ciq.number.toUpperCase() };
Cursor dataTableCursor =
- RecentCallsListActivity.this.getContentResolver().query(
+ getActivity().getContentResolver().query(
contactRef,
null, // projection
selection, // selection
@@ -410,20 +414,21 @@
// "number" is a regular phone number, so use the
// PhoneLookup table:
Cursor phonesCursor =
- RecentCallsListActivity.this.getContentResolver().query(
+ getActivity().getContentResolver().query(
Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(ciq.number)),
- PHONES_PROJECTION, null, null, null);
+ PhoneQuery._PROJECTION, null, null, null);
if (phonesCursor != null) {
if (phonesCursor.moveToFirst()) {
info = new ContactInfo();
- info.personId = phonesCursor.getLong(PERSON_ID_COLUMN_INDEX);
- info.name = phonesCursor.getString(NAME_COLUMN_INDEX);
- info.type = phonesCursor.getInt(PHONE_TYPE_COLUMN_INDEX);
- info.label = phonesCursor.getString(LABEL_COLUMN_INDEX);
- info.number = phonesCursor.getString(MATCHED_NUMBER_COLUMN_INDEX);
- info.normalizedNumber =
- phonesCursor.getString(NORMALIZED_NUMBER_COLUMN_INDEX);
+ info.personId = phonesCursor.getLong(PhoneQuery.PERSON_ID);
+ info.name = phonesCursor.getString(PhoneQuery.NAME);
+ info.type = phonesCursor.getInt(PhoneQuery.PHONE_TYPE);
+ info.label = phonesCursor.getString(PhoneQuery.LABEL);
+ info.number = phonesCursor
+ .getString(PhoneQuery.MATCHED_NUMBER);
+ info.normalizedNumber = phonesCursor
+ .getString(PhoneQuery.NORMALIZED_NUMBER);
infoUpdated = true;
}
@@ -452,6 +457,7 @@
* Handles requests for contact name and number type
* @see java.lang.Runnable#run()
*/
+ @Override
public void run() {
boolean needNotify = false;
while (!mDone) {
@@ -468,10 +474,11 @@
mRequests.wait(1000);
} catch (InterruptedException ie) {
// Ignore and continue processing requests
+ Thread.currentThread().interrupt();
}
}
}
- if (ciq != null && queryContactInfo(ciq)) {
+ if (!mDone && ciq != null && queryContactInfo(ciq)) {
needNotify = true;
}
}
@@ -490,11 +497,11 @@
CharArrayBuffer currentValue = mBuffer1;
CharArrayBuffer value = mBuffer2;
cursor.moveToFirst();
- cursor.copyStringToBuffer(NUMBER_COLUMN_INDEX, currentValue);
- int currentCallType = cursor.getInt(CALL_TYPE_COLUMN_INDEX);
+ cursor.copyStringToBuffer(CallLogQuery.NUMBER, currentValue);
+ int currentCallType = cursor.getInt(CallLogQuery.CALL_TYPE);
for (int i = 1; i < count; i++) {
cursor.moveToNext();
- cursor.copyStringToBuffer(NUMBER_COLUMN_INDEX, value);
+ cursor.copyStringToBuffer(CallLogQuery.NUMBER, value);
boolean sameNumber = equalPhoneNumbers(value, currentValue);
// Group adjacent calls with the same number. Make an exception
@@ -520,7 +527,7 @@
if (sameNumber && currentCallType == Calls.MISSED_TYPE) {
currentCallType = 0; // "not a missed call"
} else {
- currentCallType = cursor.getInt(CALL_TYPE_COLUMN_INDEX);
+ currentCallType = cursor.getInt(CallLogQuery.CALL_TYPE);
}
}
}
@@ -538,47 +545,53 @@
}
+ @VisibleForTesting
@Override
- protected View newStandAloneView(Context context, ViewGroup parent) {
+ public View newStandAloneView(Context context, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.recent_calls_list_item, parent, false);
+ View view = inflater.inflate(R.layout.call_log_list_item, parent, false);
findAndCacheViews(view);
return view;
}
+ @VisibleForTesting
@Override
- protected void bindStandAloneView(View view, Context context, Cursor cursor) {
+ public void bindStandAloneView(View view, Context context, Cursor cursor) {
bindView(context, view, cursor);
}
+ @VisibleForTesting
@Override
- protected View newChildView(Context context, ViewGroup parent) {
+ public View newChildView(Context context, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.recent_calls_list_child_item, parent, false);
+ View view = inflater.inflate(R.layout.call_log_list_child_item, parent, false);
findAndCacheViews(view);
return view;
}
+ @VisibleForTesting
@Override
- protected void bindChildView(View view, Context context, Cursor cursor) {
+ public void bindChildView(View view, Context context, Cursor cursor) {
bindView(context, view, cursor);
}
+ @VisibleForTesting
@Override
- protected View newGroupView(Context context, ViewGroup parent) {
+ public View newGroupView(Context context, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = inflater.inflate(R.layout.recent_calls_list_group_item, parent, false);
+ View view = inflater.inflate(R.layout.call_log_list_group_item, parent, false);
findAndCacheViews(view);
return view;
}
+ @VisibleForTesting
@Override
- protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
+ public void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
boolean expanded) {
- final RecentCallsListItemViews views = (RecentCallsListItemViews) view.getTag();
+ final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
int groupIndicator = expanded
? com.android.internal.R.drawable.expander_ic_maximized
: com.android.internal.R.drawable.expander_ic_minimized;
@@ -590,30 +603,34 @@
private void findAndCacheViews(View view) {
// Get the views to bind to
- RecentCallsListItemViews views = new RecentCallsListItemViews();
+ CallLogListItemViews views = new CallLogListItemViews();
views.line1View = (TextView) view.findViewById(R.id.line1);
views.labelView = (TextView) view.findViewById(R.id.label);
views.numberView = (TextView) view.findViewById(R.id.number);
views.dateView = (TextView) view.findViewById(R.id.date);
views.iconView = (ImageView) view.findViewById(R.id.call_type_icon);
views.callView = view.findViewById(R.id.call_icon);
- views.callView.setOnClickListener(this);
+ if (views.callView != null) {
+ views.callView.setOnClickListener(this);
+ }
views.groupIndicator = (ImageView) view.findViewById(R.id.groupIndicator);
views.groupSize = (TextView) view.findViewById(R.id.groupSize);
view.setTag(views);
}
public void bindView(Context context, View view, Cursor c) {
- final RecentCallsListItemViews views = (RecentCallsListItemViews) view.getTag();
+ final CallLogListItemViews views = (CallLogListItemViews) view.getTag();
- String number = c.getString(NUMBER_COLUMN_INDEX);
+ String number = c.getString(CallLogQuery.NUMBER);
String formattedNumber = null;
- String callerName = c.getString(CALLER_NAME_COLUMN_INDEX);
- int callerNumberType = c.getInt(CALLER_NUMBERTYPE_COLUMN_INDEX);
- String callerNumberLabel = c.getString(CALLER_NUMBERLABEL_COLUMN_INDEX);
- String countryIso = c.getString(COUNTRY_ISO_COLUMN_INDEX);
+ String callerName = c.getString(CallLogQuery.CALLER_NAME);
+ int callerNumberType = c.getInt(CallLogQuery.CALLER_NUMBERTYPE);
+ String callerNumberLabel = c.getString(CallLogQuery.CALLER_NUMBERLABEL);
+ String countryIso = c.getString(CallLogQuery.COUNTRY_ISO);
// Store away the number so we can call it directly if you click on the call icon
- views.callView.setTag(number);
+ if (views.callView != null) {
+ views.callView.setTag(number);
+ }
// Lookup contacts with this number
ContactInfo info = mContactInfo.get(number);
@@ -661,7 +678,9 @@
// Set the text lines and call icon.
// Assumes the call back feature is on most of the
// time. For private and unknown numbers: hide it.
- views.callView.setVisibility(View.VISIBLE);
+ if (views.callView != null) {
+ views.callView.setVisibility(View.VISIBLE);
+ }
if (!TextUtils.isEmpty(name)) {
views.line1View.setText(name);
@@ -670,8 +689,7 @@
// "type" and "label" are currently unused for SIP addresses.
CharSequence numberLabel = null;
if (!PhoneNumberUtils.isUriNumber(number)) {
- numberLabel = Phone.getDisplayLabel(context, ntype, label,
- mLabelArray);
+ numberLabel = Phone.getTypeLabel(getResources(), ntype, label);
}
views.numberView.setVisibility(View.VISIBLE);
views.numberView.setText(formattedNumber);
@@ -709,10 +727,14 @@
} else {
if (number.equals(CallerInfo.UNKNOWN_NUMBER)) {
number = getString(R.string.unknown);
- views.callView.setVisibility(View.INVISIBLE);
+ if (views.callView != null) {
+ views.callView.setVisibility(View.INVISIBLE);
+ }
} else if (number.equals(CallerInfo.PRIVATE_NUMBER)) {
number = getString(R.string.private_num);
- views.callView.setVisibility(View.INVISIBLE);
+ if (views.callView != null) {
+ views.callView.setVisibility(View.INVISIBLE);
+ }
} else if (number.equals(CallerInfo.PAYPHONE_NUMBER)) {
number = getString(R.string.payphone);
} else if (PhoneNumberUtils.extractNetworkPortion(number)
@@ -728,7 +750,7 @@
views.labelView.setVisibility(View.GONE);
}
- long date = c.getLong(DATE_COLUMN_INDEX);
+ long date = c.getLong(CallLogQuery.DATE);
// Set the date/time field by mixing relative and absolute times.
int flags = DateUtils.FORMAT_ABBREV_RELATIVE;
@@ -737,7 +759,7 @@
System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, flags));
if (views.iconView != null) {
- int type = c.getInt(CALL_TYPE_COLUMN_INDEX);
+ int type = c.getInt(CallLogQuery.CALL_TYPE);
// Set the icon
switch (type) {
case Calls.INCOMING_TYPE:
@@ -764,7 +786,7 @@
}
private static final class QueryHandler extends AsyncQueryHandler {
- private final WeakReference<RecentCallsListActivity> mActivity;
+ private final WeakReference<CallLogFragment> mFragment;
/**
* Simple handler that wraps background calls to catch
@@ -796,25 +818,26 @@
return new CatchingWorkerHandler(looper);
}
- public QueryHandler(Context context) {
- super(context.getContentResolver());
- mActivity = new WeakReference<RecentCallsListActivity>(
- (RecentCallsListActivity) context);
+ public QueryHandler(CallLogFragment fragment) {
+ super(fragment.getActivity().getContentResolver());
+ mFragment = new WeakReference<CallLogFragment>(fragment);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
- final RecentCallsListActivity activity = mActivity.get();
- if (activity != null && !activity.isFinishing()) {
- final RecentCallsListActivity.RecentCallsAdapter callsAdapter = activity.mAdapter;
+ final CallLogFragment fragment = mFragment.get();
+ if (fragment != null && fragment.getActivity() != null &&
+ !fragment.getActivity().isFinishing()) {
+ final CallLogFragment.CallLogAdapter callsAdapter = fragment.mAdapter;
callsAdapter.setLoading(false);
callsAdapter.changeCursor(cursor);
- if (activity.mScrollToTop) {
- if (activity.mList.getFirstVisiblePosition() > 5) {
- activity.mList.setSelection(5);
+ if (fragment.mScrollToTop) {
+ final ListView listView = fragment.getListView();
+ if (listView.getFirstVisiblePosition() > 5) {
+ listView.setSelection(5);
}
- activity.mList.smoothScrollToPosition(0);
- activity.mScrollToTop = false;
+ listView.smoothScrollToPosition(0);
+ fragment.mScrollToTop = false;
}
} else {
cursor.close();
@@ -823,33 +846,39 @@
}
@Override
- protected void onCreate(Bundle state) {
+ public void onCreate(Bundle state) {
super.onCreate(state);
- setContentView(R.layout.recent_calls);
-
- // Typing here goes to the dialer
- setDefaultKeyMode(DEFAULT_KEYS_DIALER);
-
- mAdapter = new RecentCallsAdapter();
- getListView().setOnCreateContextMenuListener(this);
- setListAdapter(mAdapter);
-
- mVoiceMailNumber = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE))
- .getVoiceMailNumber();
+ mVoiceMailNumber = ((TelephonyManager) getActivity().getSystemService(
+ Context.TELEPHONY_SERVICE)).getVoiceMailNumber();
mQueryHandler = new QueryHandler(this);
- mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(this);
+ mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
+
+ setHasOptionsMenu(true);
}
@Override
- protected void onStart() {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ return inflater.inflate(R.layout.call_log_fragment, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ getListView().setOnCreateContextMenuListener(this);
+ mAdapter = new CallLogAdapter();
+ setListAdapter(mAdapter);
+ }
+
+ @Override
+ public void onStart() {
mScrollToTop = true;
super.onStart();
}
@Override
- protected void onResume() {
+ public void onResume() {
// The adapter caches looked up numbers, clear it so they will get
// looked up again.
if (mAdapter != null) {
@@ -865,7 +894,7 @@
}
@Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
// Kill the requests thread
@@ -873,34 +902,12 @@
}
@Override
- protected void onDestroy() {
+ public void onDestroy() {
super.onDestroy();
mAdapter.stopRequestProcessing();
mAdapter.changeCursor(null);
}
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- super.onWindowFocusChanged(hasFocus);
-
- // Clear notifications only when window gains focus. This activity won't
- // immediately receive focus if the keyguard screen is above it.
- if (hasFocus) {
- try {
- ITelephony iTelephony =
- ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
- if (iTelephony != null) {
- iTelephony.cancelMissedCallsNotification();
- } else {
- Log.w(TAG, "Telephony service is null, can't call " +
- "cancelMissedCallsNotification");
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to clear missed calls notification due to remote exception");
- }
- }
- }
-
/**
* Format the given phone number
*
@@ -944,14 +951,14 @@
// Cancel any pending queries
mQueryHandler.cancelOperation(QUERY_TOKEN);
mQueryHandler.startQuery(QUERY_TOKEN, null, Calls.CONTENT_URI,
- CALL_LOG_PROJECTION, null, null, Calls.DEFAULT_SORT_ORDER);
+ CallLogQuery._PROJECTION, null, null, Calls.DEFAULT_SORT_ORDER);
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, MENU_ITEM_DELETE_ALL, 0, R.string.recentCalls_deleteAll)
- .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
- return true;
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ menu.add(0, OptionsMenuItems.DELETE_ALL, 0, R.string.recentCalls_deleteAll).setIcon(
+ android.R.drawable.ic_menu_close_clear_cancel);
}
@Override
@@ -966,7 +973,7 @@
Cursor cursor = (Cursor) mAdapter.getItem(menuInfo.position);
- String number = cursor.getString(NUMBER_COLUMN_INDEX);
+ String number = cursor.getString(CallLogQuery.NUMBER);
Uri numberUri = null;
boolean isVoicemail = false;
boolean isSipNumber = false;
@@ -1033,45 +1040,14 @@
menu.add(0, 0, 0, R.string.recentCalls_addToContact)
.setIntent(intent);
}
- menu.add(0, MENU_ITEM_DELETE, 0, R.string.recentCalls_removeFromRecentList);
- }
-
- @Override
- protected Dialog onCreateDialog(int id, Bundle args) {
- switch (id) {
- case DIALOG_CONFIRM_DELETE_ALL:
- return new AlertDialog.Builder(this)
- .setTitle(R.string.clearCallLogConfirmation_title)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setMessage(R.string.clearCallLogConfirmation)
- .setNegativeButton(android.R.string.cancel, null)
- .setPositiveButton(android.R.string.ok, new OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- getContentResolver().delete(Calls.CONTENT_URI, null, null);
- // TODO The change notification should do this automatically, but it
- // isn't working right now. Remove this when the change notification
- // is working properly.
- startQuery();
- }
- })
- .setCancelable(false)
- .create();
- }
- return null;
+ menu.add(0, MenuItems.DELETE, 0, R.string.recentCalls_removeFromRecentList);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case MENU_ITEM_DELETE_ALL: {
- showDialog(DIALOG_CONFIRM_DELETE_ALL);
- return true;
- }
-
- case MENU_ITEM_VIEW_CONTACTS: {
- Intent intent = new Intent(Intent.ACTION_VIEW, Contacts.CONTENT_URI);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ case OptionsMenuItems.DELETE_ALL: {
+ ClearCallLogDialog.show(getFragmentManager());
return true;
}
}
@@ -1090,7 +1066,7 @@
}
switch (item.getItemId()) {
- case MENU_ITEM_DELETE: {
+ case MenuItems.DELETE: {
Cursor cursor = (Cursor)mAdapter.getItem(menuInfo.position);
int groupSize = 1;
if (mAdapter.isGroupHeader(menuInfo.position)) {
@@ -1103,58 +1079,17 @@
sb.append(",");
cursor.moveToNext();
}
- long id = cursor.getLong(ID_COLUMN_INDEX);
+ long id = cursor.getLong(CallLogQuery.ID);
sb.append(id);
}
- getContentResolver().delete(Calls.CONTENT_URI, Calls._ID + " IN (" + sb + ")",
- null);
+ getActivity().getContentResolver().delete(Calls.CONTENT_URI,
+ Calls._ID + " IN (" + sb + ")", null);
}
}
return super.onContextItemSelected(item);
}
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL: {
- long callPressDiff = SystemClock.uptimeMillis() - event.getDownTime();
- if (callPressDiff >= ViewConfiguration.getLongPressTimeout()) {
- // Launch voice dialer
- Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- }
- return true;
- }
- }
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL:
- try {
- ITelephony phone = ITelephony.Stub.asInterface(
- ServiceManager.checkService("phone"));
- if (phone != null && !phone.isIdle()) {
- // Let the super class handle it
- break;
- }
- } catch (RemoteException re) {
- // Fall through and try to call the contact
- }
-
- callEntry(getListView().getSelectedItemPosition());
- return true;
- }
- return super.onKeyUp(keyCode, event);
- }
-
/*
* Get the number from the Contacts, if available, since sometimes
* the number provided by caller id may not be formatted properly
@@ -1172,14 +1107,12 @@
matchingNumber = ci.number;
} else {
try {
- Cursor phonesCursor =
- RecentCallsListActivity.this.getContentResolver().query(
- Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
- number),
- PHONES_PROJECTION, null, null, null);
+ Cursor phonesCursor = getActivity().getContentResolver().query(
+ Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
+ PhoneQuery._PROJECTION, null, null, null);
if (phonesCursor != null) {
if (phonesCursor.moveToFirst()) {
- matchingNumber = phonesCursor.getString(MATCHED_NUMBER_COLUMN_INDEX);
+ matchingNumber = phonesCursor.getString(PhoneQuery.MATCHED_NUMBER);
}
phonesCursor.close();
}
@@ -1195,7 +1128,8 @@
return number;
}
- private void callEntry(int position) {
+ public void callSelectedEntry() {
+ int position = getListView().getSelectedItemPosition();
if (position < 0) {
// In touch mode you may often not have something selected, so
// just call the first entry to make sure that [send] [send] calls the
@@ -1204,7 +1138,7 @@
}
final Cursor cursor = (Cursor)mAdapter.getItem(position);
if (cursor != null) {
- String number = cursor.getString(NUMBER_COLUMN_INDEX);
+ String number = cursor.getString(CallLogQuery.NUMBER);
if (TextUtils.isEmpty(number)
|| number.equals(CallerInfo.UNKNOWN_NUMBER)
|| number.equals(CallerInfo.PRIVATE_NUMBER)
@@ -1220,7 +1154,7 @@
} else {
// We're calling a regular PSTN phone number.
// Construct a tel: URI, but do some other possible cleanup first.
- int callType = cursor.getInt(CALL_TYPE_COLUMN_INDEX);
+ int callType = cursor.getInt(CallLogQuery.CALL_TYPE);
if (!number.startsWith("+") &&
(callType == Calls.INCOMING_TYPE
|| callType == Calls.MISSED_TYPE)) {
@@ -1237,23 +1171,21 @@
}
@Override
- protected void onListItemClick(ListView l, View v, int position, long id) {
+ public void onListItemClick(ListView l, View v, int position, long id) {
if (mAdapter.isGroupHeader(position)) {
mAdapter.toggleGroup(position);
} else {
- Intent intent = new Intent(this, CallDetailActivity.class);
+ Intent intent = new Intent(getActivity(), CallDetailActivity.class);
intent.setData(ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI, id));
startActivity(intent);
}
}
- @Override
- public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
- boolean globalSearch) {
- if (globalSearch) {
- super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
- } else {
- ContactsSearchManager.startSearch(this, initialQuery);
- }
+ public CallLogAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ public String getVoiceMailNumber() {
+ return mVoiceMailNumber;
}
}
diff --git a/src/com/android/contacts/calllog/ClearCallLogDialog.java b/src/com/android/contacts/calllog/ClearCallLogDialog.java
new file mode 100644
index 0000000..426732a
--- /dev/null
+++ b/src/com/android/contacts/calllog/ClearCallLogDialog.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.calllog;
+
+import com.android.contacts.R;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
+import android.app.ProgressDialog;
+import android.content.ContentResolver;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.CallLog.Calls;
+
+/**
+ * Dialog that clears the call log after confirming with the user
+ */
+public class ClearCallLogDialog extends DialogFragment {
+ /** Preferred way to show this dialog */
+ public static void show(FragmentManager fragmentManager) {
+ ClearCallLogDialog dialog = new ClearCallLogDialog();
+ dialog.show(fragmentManager, "deleteCallLog");
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final ContentResolver resolver = getActivity().getContentResolver();
+ final OnClickListener okListener = new OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ final ProgressDialog progressDialog = ProgressDialog.show(getActivity(),
+ getString(R.string.clearCallLogProgress_title),
+ "", true, false);
+ final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ resolver.delete(Calls.CONTENT_URI, null, null);
+ return null;
+ }
+ @Override
+ protected void onPostExecute(Void result) {
+ progressDialog.dismiss();
+ }
+ };
+ // TODO: Once we have the API, we should configure this ProgressDialog
+ // to only show up after a certain time (e.g. 150ms)
+ progressDialog.show();
+ task.execute();
+ }
+ };
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.clearCallLogConfirmation_title)
+ .setIconAttribute(android.R.attr.alertDialogIcon)
+ .setMessage(R.string.clearCallLogConfirmation)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok, okListener)
+ .setCancelable(true)
+ .create();
+ }
+}
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 42b3293..f3a4805 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -27,9 +27,9 @@
import com.android.contacts.TypePrecedence;
import com.android.contacts.editor.SelectAccountDialogFragment;
import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditType;
import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
import com.android.contacts.util.Constants;
import com.android.contacts.util.DataStatus;
import com.android.contacts.util.DateUtils;
@@ -164,34 +164,26 @@
* A list of distinct contact IDs included in the current contact.
*/
private ArrayList<Long> mRawContactIds = new ArrayList<Long>();
- private ArrayList<ViewEntry> mPhoneEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mSmsEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mEmailEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mPostalEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mImEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mNicknameEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mGroupEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mRelationEntries = new ArrayList<ViewEntry>();
- private ArrayList<ViewEntry> mOtherEntries = new ArrayList<ViewEntry>();
- private ArrayList<ArrayList<ViewEntry>> mSections = new ArrayList<ArrayList<ViewEntry>>();
+ private ArrayList<DetailViewEntry> mPhoneEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mSmsEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mEmailEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mPostalEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mImEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mNicknameEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mGroupEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mRelationEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mNoteEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mWebsiteEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mSipEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mEventEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<DetailViewEntry> mOtherEntries = new ArrayList<DetailViewEntry>();
+ private ArrayList<ViewEntry> mAllEntries = new ArrayList<ViewEntry>();
private LayoutInflater mInflater;
private boolean mTransitionAnimationRequested;
public ContactDetailFragment() {
// Explicit constructor for inflation
-
- // Build the list of sections. The order they're added to mSections dictates the
- // order they are displayed in the list.
- mSections.add(mPhoneEntries);
- mSections.add(mSmsEntries);
- mSections.add(mEmailEntries);
- mSections.add(mImEntries);
- mSections.add(mPostalEntries);
- mSections.add(mNicknameEntries);
- mSections.add(mOtherEntries);
- mSections.add(mRelationEntries);
- mSections.add(mGroupEntries);
}
@Override
@@ -223,9 +215,6 @@
mInflater = inflater;
- mHeaderView = (ContactDetailHeaderView) mView.findViewById(R.id.contact_header_widget);
- mHeaderView.setListener(mHeaderViewListener);
-
mListView = (ListView) mView.findViewById(android.R.id.list);
mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
mListView.setOnItemClickListener(this);
@@ -304,19 +293,22 @@
return;
}
- // Set the header
- mHeaderView.loadData(mContactData);
+ // Clear old header
+ mHeaderView = null;
// Build up the contact entries
buildEntries();
- // Collapse similar data items in select sections.
+ // Collapse similar data items for select {@link DataKind}s.
Collapser.collapseList(mPhoneEntries);
Collapser.collapseList(mSmsEntries);
Collapser.collapseList(mEmailEntries);
Collapser.collapseList(mPostalEntries);
Collapser.collapseList(mImEntries);
+ // Make one aggregated list of all entries for display to the user.
+ flattenAllLists();
+
if (mAdapter == null) {
mAdapter = new ViewAdapter();
mListView.setAdapter(mAdapter);
@@ -350,10 +342,7 @@
mHasSip = PhoneCapabilityTester.isSipPhone(mContext);
// Clear out the old entries
- final int numSections = mSections.size();
- for (int i = 0; i < numSections; i++) {
- mSections.get(i).clear();
- }
+ mAllEntries.clear();
mRawContactIds.clear();
@@ -409,8 +398,8 @@
accountType, mimeType);
if (kind == null) continue;
- final ViewEntry entry = ViewEntry.fromValues(mContext, mimeType, kind, dataId,
- entryValues, mContactData.isDirectoryEntry(),
+ final DetailViewEntry entry = DetailViewEntry.fromValues(mContext, mimeType, kind,
+ dataId, entryValues, mContactData.isDirectoryEntry(),
mContactData.getDirectoryId());
final boolean hasData = !TextUtils.isEmpty(entry.data);
@@ -464,8 +453,8 @@
final String imMime = Im.CONTENT_ITEM_TYPE;
final DataKind imKind = accountTypes.getKindOrFallback(accountType,
imMime);
- final ViewEntry imEntry = ViewEntry.fromValues(mContext, imMime, imKind,
- dataId, entryValues, mContactData.isDirectoryEntry(),
+ final DetailViewEntry imEntry = DetailViewEntry.fromValues(mContext, imMime,
+ imKind, dataId, entryValues, mContactData.isDirectoryEntry(),
mContactData.getDirectoryId());
buildImActions(imEntry, entryValues);
imEntry.applyStatus(status, false);
@@ -507,7 +496,7 @@
// Build note entries
entry.uri = null;
entry.maxLines = 100;
- mOtherEntries.add(entry);
+ mNoteEntries.add(entry);
} else if (Website.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
// Build Website entries
entry.uri = null;
@@ -519,7 +508,7 @@
} catch (ParseException e) {
Log.e(TAG, "Couldn't parse website: " + entry.data);
}
- mOtherEntries.add(entry);
+ mWebsiteEntries.add(entry);
} else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
// Build SipAddress entries
entry.uri = null;
@@ -531,17 +520,17 @@
entry.intent = null;
entry.actionIcon = -1;
}
- mOtherEntries.add(entry);
- // TODO: Consider moving the SipAddress into its own
- // section (rather than lumping it in with mOtherEntries)
- // so that we can reposition it right under the phone number.
+ mSipEntries.add(entry);
+ // TODO: Now that SipAddress is in its own list of entries
+ // (instead of grouped in mOtherEntries), consider
+ // repositioning it right under the phone number.
// (Then, we'd also update FallbackAccountType.java to set
// secondary=false for this field, and tweak the weight
// of its DataKind.)
} else if (Event.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
entry.data = DateUtils.formatDate(mContext, entry.data);
entry.uri = null;
- mOtherEntries.add(entry);
+ mEventEntries.add(entry);
} else if (Relation.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
entry.intent = new Intent(Intent.ACTION_SEARCH);
entry.intent.putExtra(SearchManager.QUERY, entry.data);
@@ -567,7 +556,7 @@
}
if (!groups.isEmpty()) {
- ViewEntry entry = new ViewEntry();
+ DetailViewEntry entry = new DetailViewEntry();
Collections.sort(groups);
StringBuilder sb = new StringBuilder();
int size = groups.size();
@@ -585,6 +574,49 @@
}
/**
+ * Collapse all contact detail entries into one aggregated list with a {@link HeaderViewEntry}
+ * at the top.
+ */
+ private void flattenAllLists() {
+ // All contacts should have a header view (even if there is no data for the contact).
+ mAllEntries.add(new HeaderViewEntry());
+
+ flattenList(mPhoneEntries);
+ flattenList(mSmsEntries);
+ flattenList(mEmailEntries);
+ flattenList(mImEntries);
+ flattenList(mPostalEntries);
+ flattenList(mNicknameEntries);
+ flattenList(mNoteEntries);
+ flattenList(mWebsiteEntries);
+ flattenList(mSipEntries);
+ flattenList(mEventEntries);
+ flattenList(mOtherEntries);
+ flattenList(mRelationEntries);
+ flattenList(mGroupEntries);
+ }
+
+ /**
+ * Iterate through {@link DetailViewEntry} in the given list and add it to a list of all
+ * entries. Add a {@link SeparatorViewEntry} at the end if the length of the list was not 0.
+ * Clear the original list.
+ */
+ private void flattenList(ArrayList<DetailViewEntry> entries) {
+ int count = entries.size();
+
+ for (int i = 0; i < count; i++) {
+ mAllEntries.add(entries.get(i));
+ }
+
+ if (count > 0) {
+ mAllEntries.add(new SeparatorViewEntry());
+ }
+
+ // Clear old list because it's not needed anymore.
+ entries.clear();
+ }
+
+ /**
* Maps group ID to the corresponding group name, collapses all synonymous groups.
* Ignores default groups (e.g. My Contacts) and favorites groups.
*/
@@ -621,7 +653,7 @@
* {@link Email} row. If the result is non-null, it either contains one or two Intents
* (e.g. [Text, Videochat] or just [Text])
*/
- public static void buildImActions(ViewEntry entry, ContentValues values) {
+ public static void buildImActions(DetailViewEntry entry, ContentValues values) {
final boolean isEmail = Email.CONTENT_ITEM_TYPE.equals(values.getAsString(Data.MIMETYPE));
if (!isEmail && !isProtocolValid(values)) {
@@ -690,15 +722,65 @@
}
/**
- * A basic structure with the data for a contact entry in the list.
+ * Base class for an item in the {@link ViewAdapter} list of data, which is
+ * supplied to the {@link ListView}.
*/
- static class ViewEntry implements Collapsible<ViewEntry> {
+ static class ViewEntry {
+ private final int viewTypeForAdapter;
+ protected long id = -1;
+ /** Whether or not the entry can be focused on or not. */
+ protected boolean isEnabled = false;
+
+ ViewEntry(int viewType) {
+ viewTypeForAdapter = viewType;
+ }
+
+ int getViewType() {
+ return viewTypeForAdapter;
+ }
+
+ long getId() {
+ return id;
+ }
+
+ boolean isEnabled(){
+ return isEnabled;
+ }
+ }
+
+ /**
+ * Header item in the {@link ViewAdapter} list of data.
+ */
+ static class HeaderViewEntry extends ViewEntry {
+
+ HeaderViewEntry() {
+ super(ViewAdapter.VIEW_TYPE_HEADER_ENTRY);
+ }
+
+ }
+
+ /**
+ * Separator between items of the same {@link DataKind} in the
+ * {@link ViewAdapter} list of data.
+ */
+ static class SeparatorViewEntry extends ViewEntry {
+
+ SeparatorViewEntry() {
+ super(ViewAdapter.VIEW_TYPE_SEPARATOR_ENTRY);
+ }
+
+ }
+
+ /**
+ * An item with a single detail for a contact in the {@link ViewAdapter}
+ * list of data.
+ */
+ static class DetailViewEntry extends ViewEntry implements Collapsible<DetailViewEntry> {
public int type = -1;
public String kind;
public String typeString;
public String data;
public Uri uri;
- public long id = 0;
public int maxLines = 1;
public String mimetype;
@@ -717,17 +799,19 @@
public CharSequence footerLine = null;
- ViewEntry() {
+ DetailViewEntry() {
+ super(ViewAdapter.VIEW_TYPE_DETAIL_ENTRY);
+ isEnabled = true;
}
/**
- * Build new {@link ViewEntry} and populate from the given values.
+ * Build new {@link DetailViewEntry} and populate from the given values.
*/
- public static ViewEntry fromValues(Context context, String mimeType, DataKind kind,
+ public static DetailViewEntry fromValues(Context context, String mimeType, DataKind kind,
long dataId, ContentValues values, boolean isDirectoryEntry, long directoryId) {
- final ViewEntry entry = new ViewEntry();
- entry.context = context;
+ final DetailViewEntry entry = new DetailViewEntry();
entry.id = dataId;
+ entry.context = context;
entry.uri = ContentUris.withAppendedId(Data.CONTENT_URI, entry.id);
if (isDirectoryEntry) {
entry.uri = entry.uri.buildUpon().appendQueryParameter(
@@ -770,13 +854,13 @@
}
/**
- * Apply given {@link DataStatus} values over this {@link ViewEntry}
+ * Apply given {@link DataStatus} values over this {@link DetailViewEntry}
*
* @param fillData When true, the given status replaces {@link #data}
* and {@link #footerLine}. Otherwise only {@link #presence}
* is updated.
*/
- public ViewEntry applyStatus(DataStatus status, boolean fillData) {
+ public DetailViewEntry applyStatus(DataStatus status, boolean fillData) {
presence = status.getPresence();
if (fillData && status.isValid()) {
this.data = status.getStatus().toString();
@@ -787,7 +871,7 @@
}
@Override
- public boolean collapseWith(ViewEntry entry) {
+ public boolean collapseWith(DetailViewEntry entry) {
// assert equal collapse keys
if (!shouldCollapseWith(entry)) {
return false;
@@ -816,13 +900,13 @@
// uri, and contactdId, shouldn't make a difference. Just keep the original.
// Keep track of all the ids that have been collapsed with this one.
- ids.add(entry.id);
+ ids.add(entry.getId());
collapseCount++;
return true;
}
@Override
- public boolean shouldCollapseWith(ViewEntry entry) {
+ public boolean shouldCollapseWith(DetailViewEntry entry) {
if (entry == null) {
return false;
}
@@ -845,23 +929,64 @@
/** Cache of the children views of a row */
private static class ViewCache {
- public View kindDivider;
- public View inKindDivider;
- public View lineBelowLast;
public TextView kind;
public TextView type;
public TextView data;
public TextView footer;
- public ImageView actionIcon;
public ImageView presenceIcon;
public ImageView secondaryActionButton;
+ public View secondaryActionButtonContainer;
public View secondaryActionDivider;
}
private final class ViewAdapter extends BaseAdapter {
+
+ public static final int VIEW_TYPE_DETAIL_ENTRY = 0;
+ public static final int VIEW_TYPE_HEADER_ENTRY = 1;
+ public static final int VIEW_TYPE_SEPARATOR_ENTRY = 2;
+ private static final int VIEW_TYPE_COUNT = 3;
+
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final ViewEntry entry = getEntry(position);
+ switch (getItemViewType(position)) {
+ case VIEW_TYPE_HEADER_ENTRY:
+ return getHeaderEntryView(convertView, parent);
+ case VIEW_TYPE_SEPARATOR_ENTRY:
+ return getSeparatorEntryView(convertView, parent);
+ case VIEW_TYPE_DETAIL_ENTRY:
+ return getDetailEntryView(position, convertView, parent);
+ default:
+ throw new IllegalStateException("Invalid view type ID " +
+ getItemViewType(position));
+ }
+ }
+
+ private View getHeaderEntryView(View convertView, ViewGroup parent) {
+ // We don't want to rely on the recycled header view because it may
+ // have been left over from a previously viewed contact (since we
+ // reuse the adapter), so we would have to bind the data to the
+ // header each time. However, since there is only 1 header per list,
+ // just hold onto the original header view for this contact and
+ // return that each time.
+ if (mHeaderView != null) {
+ return mHeaderView;
+ }
+ mHeaderView = (ContactDetailHeaderView) mInflater.inflate(
+ R.layout.contact_detail_header_view_list_item, parent, false);
+ mHeaderView.setListener(mHeaderViewListener);
+ mHeaderView.loadData(mContactData);
+ return mHeaderView;
+ }
+
+ private View getSeparatorEntryView(View convertView, ViewGroup parent) {
+ if (convertView != null) {
+ return convertView;
+ }
+ return mInflater.inflate(R.layout.contact_detail_separator_list_item, parent, false);
+ }
+
+ private View getDetailEntryView(int position, View convertView, ViewGroup parent) {
+ final DetailViewEntry entry = (DetailViewEntry) getItem(position);
final View v;
final ViewCache viewCache;
@@ -876,46 +1001,49 @@
// Cache the children
viewCache = new ViewCache();
viewCache.kind = (TextView) v.findViewById(R.id.kind);
- viewCache.kindDivider = v.findViewById(R.id.kind_divider);
- viewCache.lineBelowLast = v.findViewById(R.id.line_below_last);
- viewCache.inKindDivider = v.findViewById(R.id.in_kind_divider);
viewCache.type = (TextView) v.findViewById(R.id.type);
viewCache.data = (TextView) v.findViewById(R.id.data);
viewCache.footer = (TextView) v.findViewById(R.id.footer);
- viewCache.actionIcon = (ImageView) v.findViewById(R.id.action_icon);
viewCache.presenceIcon = (ImageView) v.findViewById(R.id.presence_icon);
viewCache.secondaryActionButton = (ImageView) v.findViewById(
R.id.secondary_action_button);
- viewCache.secondaryActionButton.setOnClickListener(mSecondaryActionClickListener);
+ viewCache.secondaryActionButtonContainer = v.findViewById(
+ R.id.secondary_action_button_container);
+ viewCache.secondaryActionButtonContainer.setOnClickListener(
+ mSecondaryActionClickListener);
viewCache.secondaryActionDivider = v.findViewById(R.id.divider);
v.setTag(viewCache);
}
- final ViewEntry previousEntry = position == 0 ? null : getEntry(position - 1);
- final boolean isFirstOfItsKind =
- previousEntry == null ? true : !previousEntry.kind.equals(entry.kind);
- final boolean isLast = position == getCount() - 1;
+ final ViewEntry previousEntry = position == 0 ? null : getItem(position - 1);
+ final boolean isFirstOfItsKind = (previousEntry == null) ? true :
+ (previousEntry.getViewType() != VIEW_TYPE_DETAIL_ENTRY);
// Bind the data to the view
- bindView(v, entry, isFirstOfItsKind, isLast);
+ bindView(v, entry, isFirstOfItsKind);
return v;
}
- protected void bindView(View view, ViewEntry entry, boolean isFirstOfItsKind,
- boolean isLast) {
+ private void bindView(View view, DetailViewEntry entry, boolean isFirstOfItsKind) {
final Resources resources = mContext.getResources();
ViewCache views = (ViewCache) view.getTag();
- views.kind.setText(isFirstOfItsKind ? entry.kind : "");
- views.kindDivider.setVisibility(isFirstOfItsKind ? View.VISIBLE : View.GONE);
- views.inKindDivider.setVisibility(isFirstOfItsKind ? View.GONE : View.VISIBLE);
- if (views.lineBelowLast != null) {
- views.lineBelowLast.setVisibility(isLast ? View.VISIBLE : View.GONE);
+ if (isFirstOfItsKind) {
+ views.kind.setText(entry.kind != null ? entry.kind.toUpperCase() : "");
+ views.kind.setVisibility(View.VISIBLE);
+ } else {
+ views.kind.setVisibility(View.GONE);
}
- views.type.setText(entry.typeString);
- views.type.setVisibility(
- TextUtils.isEmpty(entry.typeString) ? View.GONE : View.VISIBLE);
+ if (!TextUtils.isEmpty(entry.typeString)) {
+ views.type.setText(entry.typeString.toUpperCase());
+ views.type.setVisibility(View.VISIBLE);
+ if (isFirstOfItsKind) {
+ views.kind.setVisibility(View.GONE);
+ }
+ } else {
+ views.type.setVisibility(View.GONE);
+ }
views.data.setText(entry.data);
setMaxLines(views.data, entry.maxLines);
@@ -928,24 +1056,6 @@
views.footer.setVisibility(View.GONE);
}
- // Set the action icon
- final ImageView action = views.actionIcon;
- if (entry.actionIcon != -1) {
- Drawable actionIcon;
- if (entry.resPackageName != null) {
- // Load external resources through PackageManager
- actionIcon = mContext.getPackageManager().getDrawable(entry.resPackageName,
- entry.actionIcon, null);
- } else {
- actionIcon = resources.getDrawable(entry.actionIcon);
- }
- action.setImageDrawable(actionIcon);
- action.setVisibility(View.VISIBLE);
- } else {
- // Things should still line up as if there was an icon, so make it invisible
- action.setVisibility(View.INVISIBLE);
- }
-
// Set the presence icon
final Drawable presenceIcon = ContactPresenceIconUtil.getPresenceIcon(
mContext, entry.presence);
@@ -972,11 +1082,11 @@
if (entry.secondaryIntent != null && secondaryActionIcon != null) {
secondaryActionView.setImageDrawable(secondaryActionIcon);
- secondaryActionView.setTag(entry);
- secondaryActionView.setVisibility(View.VISIBLE);
+ views.secondaryActionButtonContainer.setTag(entry);
+ views.secondaryActionButtonContainer.setVisibility(View.VISIBLE);
views.secondaryActionDivider.setVisibility(View.VISIBLE);
} else {
- secondaryActionView.setVisibility(View.GONE);
+ views.secondaryActionButtonContainer.setVisibility(View.GONE);
views.secondaryActionDivider.setVisibility(View.GONE);
}
}
@@ -998,8 +1108,9 @@
if (mListener == null) return;
if (v == null) return;
final ViewEntry entry = (ViewEntry) v.getTag();
- if (entry == null) return;
- final Intent intent = entry.secondaryIntent;
+ if (entry == null || !(entry instanceof DetailViewEntry)) return;
+ final DetailViewEntry detailViewEntry = (DetailViewEntry) entry;
+ final Intent intent = detailViewEntry.secondaryIntent;
if (intent == null) return;
mListener.onItemClicked(intent);
}
@@ -1007,40 +1118,42 @@
@Override
public int getCount() {
- int count = 0;
- final int numSections = mSections.size();
- for (int i = 0; i < numSections; i++) {
- final ArrayList<ViewEntry> section = mSections.get(i);
- count += section.size();
- }
- return count;
+ return mAllEntries.size();
}
@Override
- public Object getItem(int position) {
- return getEntry(position);
+ public ViewEntry getItem(int position) {
+ return mAllEntries.get(position);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return mAllEntries.get(position).getViewType();
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return VIEW_TYPE_COUNT;
}
@Override
public long getItemId(int position) {
- final ViewEntry entry = getEntry(position);
+ final ViewEntry entry = mAllEntries.get(position);
if (entry != null) {
- return entry.id;
+ return entry.getId();
}
return -1;
}
- private ViewEntry getEntry(int position) {
- final int numSections = mSections.size();
- for (int i = 0; i < numSections; i++) {
- final ArrayList<ViewEntry> section = mSections.get(i);
- final int sectionSize = section.size();
- if (position < sectionSize) {
- return section.get(position);
- }
- position -= sectionSize;
- }
- return null;
+ @Override
+ public boolean areAllItemsEnabled() {
+ // Header will always be an item that is not enabled.
+ return false;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItem(position).isEnabled();
}
}
@@ -1173,7 +1286,7 @@
}
@Override
- public void onAccountChosen(Account account) {
+ public void onAccountChosen(int requestCode, Account account) {
createCopy(account);
}
@@ -1186,9 +1299,9 @@
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (mListener == null) return;
- final ViewEntry entry = mAdapter.getEntry(position);
- if (entry == null) return;
- final Intent intent = entry.intent;
+ final ViewEntry entry = mAdapter.getItem(position);
+ if (entry == null || !(entry instanceof DetailViewEntry)) return;
+ final Intent intent = ((DetailViewEntry) entry).intent;
if (intent == null) return;
mListener.onItemClicked(intent);
}
@@ -1224,7 +1337,7 @@
int index = mListView.getSelectedItemPosition();
if (index != -1) {
- final ViewEntry entry = mAdapter.getEntry(index);
+ final DetailViewEntry entry = (DetailViewEntry) mAdapter.getItem(index);
if (entry != null && entry.intent != null &&
entry.intent.getAction() == Intent.ACTION_CALL_PRIVILEGED) {
mContext.startActivity(entry.intent);
@@ -1262,7 +1375,7 @@
@Override
public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
- if (!((ContactLoader)loader).getLookupUri().equals(mLookupUri)) {
+ if (!mLookupUri.equals(data.getUri())) {
return;
}
diff --git a/src/com/android/contacts/detail/ContactDetailHeaderView.java b/src/com/android/contacts/detail/ContactDetailHeaderView.java
index 4b211b6..795ed62 100644
--- a/src/com/android/contacts/detail/ContactDetailHeaderView.java
+++ b/src/com/android/contacts/detail/ContactDetailHeaderView.java
@@ -20,6 +20,8 @@
import com.android.contacts.ContactLoader.Result;
import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
+import com.android.contacts.format.FormatUtils;
+import com.android.contacts.preference.ContactsPreferences;
import com.android.contacts.util.ContactBadgeUtil;
import android.content.ClipData;
@@ -31,10 +33,13 @@
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Typeface;
import android.net.Uri;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.DisplayNameSources;
+import android.text.Spanned;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -122,7 +127,8 @@
public void loadData(ContactLoader.Result contactData) {
mContactUri = contactData.getLookupUri();
- setDisplayName(contactData.getDisplayName(), contactData.getPhoneticName());
+ setDisplayName(contactData.getDisplayName(), contactData.getAltDisplayName(),
+ contactData.getPhoneticName());
setCompany(contactData);
if (contactData.isLoadingPhoto()) {
setPhoto(null, false);
@@ -188,8 +194,38 @@
/**
* Set the display name and phonetic name to show in the header.
*/
- private void setDisplayName(CharSequence displayName, CharSequence phoneticName) {
- mDisplayNameView.setText(displayName);
+ private void setDisplayName(CharSequence displayName, CharSequence altDisplayName,
+ CharSequence phoneticName) {
+
+ // Check the preference for display name ordering, and bold the contact's first name if
+ // possible.
+ ContactsPreferences prefs = new ContactsPreferences(getContext());
+ CharSequence styledName = "";
+ if (!TextUtils.isEmpty(displayName) && !TextUtils.isEmpty(altDisplayName)) {
+ if (prefs.getDisplayOrder() == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ int overlapPoint = FormatUtils.overlapPoint(
+ displayName.toString(), altDisplayName.toString());
+ if (overlapPoint > 0) {
+ styledName = FormatUtils.applyStyleToSpan(Typeface.BOLD,
+ displayName, 0, overlapPoint, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ styledName = displayName;
+ }
+ } else {
+ // Displaying alternate display name.
+ int overlapPoint = FormatUtils.overlapPoint(
+ altDisplayName.toString(), displayName.toString());
+ if (overlapPoint > 0) {
+ styledName = FormatUtils.applyStyleToSpan(Typeface.BOLD,
+ altDisplayName, overlapPoint, altDisplayName.length(),
+ Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ } else {
+ styledName = altDisplayName;
+ }
+ }
+ }
+ mDisplayNameView.setText(styledName);
+
if (TextUtils.isEmpty(phoneticName)) {
mPhoneticNameView.setVisibility(View.GONE);
} else {
diff --git a/src/com/android/contacts/TwelveKeyDialer.java b/src/com/android/contacts/dialpad/DialpadFragment.java
similarity index 85%
rename from src/com/android/contacts/TwelveKeyDialer.java
rename to src/com/android/contacts/dialpad/DialpadFragment.java
index b93375c..58ffb9e 100644
--- a/src/com/android/contacts/TwelveKeyDialer.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,20 @@
* limitations under the License.
*/
-package com.android.contacts;
+package com.android.contacts.dialpad;
+import com.android.contacts.ContactsUtils;
+import com.android.contacts.R;
+import com.android.contacts.SpecialCharSequenceMgr;
+import com.android.contacts.activities.DialtactsActivity;
import com.android.internal.telephony.ITelephony;
import com.android.phone.CallLogAsync;
import com.android.phone.HapticFeedback;
import android.app.Activity;
-import android.content.ActivityNotFoundException;
+import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -36,12 +39,11 @@
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.provider.Settings;
+import android.provider.Contacts.Intents.Insert;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
import android.provider.Contacts.PhonesColumns;
-import android.provider.Contacts.Intents.Insert;
+import android.provider.Settings;
import android.telephony.PhoneNumberFormattingTextWatcher;
import android.telephony.PhoneNumberUtils;
import android.telephony.PhoneStateListener;
@@ -54,12 +56,10 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.Window;
-import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.EditText;
@@ -68,14 +68,15 @@
import android.widget.TextView;
/**
- * Dialer activity that displays the typical twelve key interface.
+ * Fragment that displays a twelve-key phone dialpad.
*/
-@SuppressWarnings("deprecation")
-public class TwelveKeyDialer extends Activity implements View.OnClickListener,
+public class DialpadFragment extends Fragment
+ implements View.OnClickListener,
View.OnLongClickListener, View.OnKeyListener,
AdapterView.OnItemClickListener, TextWatcher {
+ private static final String TAG = "DialpadFragment";
+
private static final String EMPTY_NUMBER = "";
- private static final String TAG = "TwelveKeyDialer";
/** The length of DTMF tones in milliseconds */
private static final int TONE_LENGTH_MS = 150;
@@ -173,7 +174,7 @@
}
public void afterTextChanged(Editable input) {
- if (SpecialCharSequenceMgr.handleChars(this, input.toString(), mDigits)) {
+ if (SpecialCharSequenceMgr.handleChars(getActivity(), input.toString(), mDigits)) {
// A special sequence was entered, clear the digits
mDigits.getText().clear();
}
@@ -189,24 +190,31 @@
}
@Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ public void onCreate(Bundle state) {
+ super.onCreate(state);
- mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(this);
- Resources r = getResources();
- // Do not show title in the case the device is in carmode.
- if ((r.getConfiguration().uiMode & Configuration.UI_MODE_TYPE_MASK) ==
- Configuration.UI_MODE_TYPE_CAR) {
- requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mCurrentCountryIso = ContactsUtils.getCurrentCountryIso(getActivity());
+
+ try {
+ mHaptic.init(getActivity(),
+ getResources().getBoolean(R.bool.config_enable_dialer_key_vibration));
+ } catch (Resources.NotFoundException nfe) {
+ Log.e(TAG, "Vibrate control bool missing.", nfe);
}
- // Set the content view
- setContentView(getContentViewResource());
+
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ View fragmentView = inflater.inflate(R.layout.dialpad_fragment, container, false);
// Load up the resources for the text field.
+ Resources r = getResources();
mDigitsBackground = r.getDrawable(R.drawable.btn_dial_textfield_active);
mDigitsEmptyBackground = r.getDrawable(R.drawable.btn_dial_textfield);
- mDigits = (EditText) findViewById(R.id.digits);
+ mDigits = (EditText) fragmentView.findViewById(R.id.digits);
mDigits.setKeyListener(DialerKeyListener.getInstance());
mDigits.setOnClickListener(this);
mDigits.setOnKeyListener(this);
@@ -214,12 +222,12 @@
maybeAddNumberFormatting();
// Check for the presence of the keypad
- View view = findViewById(R.id.one);
- if (view != null) {
- setupKeypad();
+ View oneButton = fragmentView.findViewById(R.id.one);
+ if (oneButton != null) {
+ setupKeypad(fragmentView);
}
- mVoicemailDialAndDeleteRow = findViewById(R.id.voicemailAndDialAndDelete);
+ mVoicemailDialAndDeleteRow = fragmentView.findViewById(R.id.voicemailAndDialAndDelete);
initVoicemailButton();
@@ -233,12 +241,11 @@
mDialButton = null;
}
- view = mVoicemailDialAndDeleteRow.findViewById(R.id.deleteButton);
- view.setOnClickListener(this);
- view.setOnLongClickListener(this);
- mDelete = view;
+ mDelete = mVoicemailDialAndDeleteRow.findViewById(R.id.deleteButton);
+ mDelete.setOnClickListener(this);
+ mDelete.setOnLongClickListener(this);
- mDialpad = findViewById(R.id.dialpad); // This is null in landscape mode.
+ mDialpad = fragmentView.findViewById(R.id.dialpad); // This is null in landscape mode.
// In landscape we put the keyboard in phone mode.
// In portrait we prevent the soft keyboard to show since the
@@ -250,47 +257,42 @@
}
// Set up the "dialpad chooser" UI; see showDialpadChooser().
- mDialpadChooser = (ListView) findViewById(R.id.dialpadChooser);
+ mDialpadChooser = (ListView) fragmentView.findViewById(R.id.dialpadChooser);
mDialpadChooser.setOnItemClickListener(this);
- if (!resolveIntent() && icicle != null) {
- super.onRestoreInstanceState(icicle);
- }
-
- try {
- mHaptic.init(this, r.getBoolean(R.bool.config_enable_dialer_key_vibration));
- } catch (Resources.NotFoundException nfe) {
- Log.e(TAG, "Vibrate control bool missing.", nfe);
- }
-
+ return fragmentView;
}
- @Override
- protected void onRestoreInstanceState(Bundle icicle) {
- // Do nothing, state is restored in onCreate() if needed
+ public EditText getDigitsWidget() {
+ return mDigits;
}
- protected void maybeAddNumberFormatting() {
+ private void maybeAddNumberFormatting() {
mDigits.addTextChangedListener(new PhoneNumberFormattingTextWatcher(mCurrentCountryIso));
}
/**
- * Overridden by subclasses to control the resource used by the content view.
+ * Handles the intent that launched us.
+ *
+ * We can be launched either with ACTION_DIAL or ACTION_VIEW (which
+ * may include a phone number to pre-load), or ACTION_MAIN (which just
+ * brings up a blank dialpad).
+ *
+ * @return true IFF the current intent has the DialtactsActivity.EXTRA_IGNORE_STATE
+ * extra set to true, which indicates (to our container) that we should ignore
+ * any possible saved state, and instead reset our state based on the parent's
+ * intent.
*/
- protected int getContentViewResource() {
- return R.layout.twelve_key_dialer;
- }
-
- private boolean resolveIntent() {
+ public boolean resolveIntent() {
boolean ignoreState = false;
// Find the proper intent
final Intent intent;
- if (isChild()) {
- intent = getParent().getIntent();
+ if (getActivity().isChild()) {
+ intent = getActivity().getParent().getIntent();
ignoreState = intent.getBooleanExtra(DialtactsActivity.EXTRA_IGNORE_STATE, false);
} else {
- intent = getIntent();
+ intent = getActivity().getIntent();
}
// Log.i(TAG, "==> resolveIntent(): intent: " + intent);
@@ -317,7 +319,7 @@
if (People.CONTENT_ITEM_TYPE.equals(type)
|| Phones.CONTENT_ITEM_TYPE.equals(type)) {
// Query the phone number
- Cursor c = getContentResolver().query(intent.getData(),
+ Cursor c = getActivity().getContentResolver().query(intent.getData(),
new String[] {PhonesColumns.NUMBER, PhonesColumns.NUMBER_KEY},
null, null, null);
if (c != null) {
@@ -363,7 +365,7 @@
return ignoreState;
}
- protected void setFormattedDigits(String data, String normalizedNumber) {
+ private void setFormattedDigits(String data, String normalizedNumber) {
// strip the non-dialable numbers out of the data string.
String dialString = PhoneNumberUtils.extractNetworkPortion(data);
dialString =
@@ -377,16 +379,32 @@
}
}
- @Override
- protected void onNewIntent(Intent newIntent) {
- setIntent(newIntent);
- resolveIntent();
+ private void setupKeypad(View fragmentView) {
+ // Setup the listeners for the buttons
+ View view = fragmentView.findViewById(R.id.one);
+ view.setOnClickListener(this);
+ view.setOnLongClickListener(this);
+
+ fragmentView.findViewById(R.id.two).setOnClickListener(this);
+ fragmentView.findViewById(R.id.three).setOnClickListener(this);
+ fragmentView.findViewById(R.id.four).setOnClickListener(this);
+ fragmentView.findViewById(R.id.five).setOnClickListener(this);
+ fragmentView.findViewById(R.id.six).setOnClickListener(this);
+ fragmentView.findViewById(R.id.seven).setOnClickListener(this);
+ fragmentView.findViewById(R.id.eight).setOnClickListener(this);
+ fragmentView.findViewById(R.id.nine).setOnClickListener(this);
+ fragmentView.findViewById(R.id.star).setOnClickListener(this);
+
+ view = fragmentView.findViewById(R.id.zero);
+ view.setOnClickListener(this);
+ view.setOnLongClickListener(this);
+
+ fragmentView.findViewById(R.id.pound).setOnClickListener(this);
}
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
+ // Do some stuff that needs to happen only once, but which we
+ // can't do directly from onCreate().
+ public void onPostCreate() {
// This can't be done in onCreate(), since the auto-restoring of the digits
// will play DTMF tones for all the old digits if it is when onRestoreSavedInstanceState()
// is called. This method will be called every time the activity is created, and
@@ -394,31 +412,8 @@
mDigits.addTextChangedListener(this);
}
- private void setupKeypad() {
- // Setup the listeners for the buttons
- View view = findViewById(R.id.one);
- view.setOnClickListener(this);
- view.setOnLongClickListener(this);
-
- findViewById(R.id.two).setOnClickListener(this);
- findViewById(R.id.three).setOnClickListener(this);
- findViewById(R.id.four).setOnClickListener(this);
- findViewById(R.id.five).setOnClickListener(this);
- findViewById(R.id.six).setOnClickListener(this);
- findViewById(R.id.seven).setOnClickListener(this);
- findViewById(R.id.eight).setOnClickListener(this);
- findViewById(R.id.nine).setOnClickListener(this);
- findViewById(R.id.star).setOnClickListener(this);
-
- view = findViewById(R.id.zero);
- view.setOnClickListener(this);
- view.setOnLongClickListener(this);
-
- findViewById(R.id.pound).setOnClickListener(this);
- }
-
@Override
- protected void onResume() {
+ public void onResume() {
super.onResume();
// Query the last dialed number. Do it first because hitting
@@ -426,7 +421,7 @@
queryLastOutgoingCall();
// retrieve the DTMF tone play back setting.
- mDTMFToneEnabled = Settings.System.getInt(getContentResolver(),
+ mDTMFToneEnabled = Settings.System.getInt(getActivity().getContentResolver(),
Settings.System.DTMF_TONE_WHEN_DIALING, 1) == 1;
// Retrieve the haptic feedback setting.
@@ -434,14 +429,14 @@
// if the mToneGenerator creation fails, just continue without it. It is
// a local audio signal, and is not as important as the dtmf tone itself.
- synchronized(mToneGeneratorLock) {
+ synchronized (mToneGeneratorLock) {
if (mToneGenerator == null) {
try {
// we want the user to be able to control the volume of the dial tones
// outside of a call, so we use the stream type that is also mapped to the
// volume control keys for this activity
mToneGenerator = new ToneGenerator(DIAL_TONE_STREAM_TYPE, TONE_RELATIVE_VOLUME);
- setVolumeControlStream(DIAL_TONE_STREAM_TYPE);
+ getActivity().setVolumeControlStream(DIAL_TONE_STREAM_TYPE);
} catch (RuntimeException e) {
Log.w(TAG, "Exception caught while creating local tone generator: " + e);
mToneGenerator = null;
@@ -449,7 +444,7 @@
}
}
- Activity parent = getParent();
+ Activity parent = getActivity().getParent();
// See if we were invoked with a DIAL intent. If we were, fill in the appropriate
// digits in the dialer field.
if (parent != null && parent instanceof DialtactsActivity) {
@@ -462,7 +457,8 @@
// While we're in the foreground, listen for phone state changes,
// purely so that we can take down the "dialpad chooser" if the
// phone becomes idle while the chooser UI is visible.
- TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+ TelephonyManager telephonyManager =
+ (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
// Potentially show hint text in the mDigits field when the user
@@ -489,27 +485,15 @@
}
@Override
- public void onWindowFocusChanged(boolean hasFocus) {
- if (hasFocus) {
- // Hide soft keyboard, if visible (it's fugly over button dialer).
- // The only known case where this will be true is when launching the dialer with
- // ACTION_DIAL via a soft keyboard. we dismiss it here because we don't
- // have a window token yet in onCreate / onNewIntent
- InputMethodManager inputMethodManager = (InputMethodManager)
- getSystemService(Context.INPUT_METHOD_SERVICE);
- inputMethodManager.hideSoftInputFromWindow(mDigits.getWindowToken(), 0);
- }
- }
-
- @Override
- protected void onPause() {
+ public void onPause() {
super.onPause();
// Stop listening for phone state changes.
- TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
+ TelephonyManager telephonyManager =
+ (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
- synchronized(mToneGeneratorLock) {
+ synchronized (mToneGeneratorLock) {
if (mToneGenerator != null) {
mToneGenerator.release();
mToneGenerator = null;
@@ -521,22 +505,25 @@
}
@Override
- public boolean onCreateOptionsMenu(Menu menu) {
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+
mAddToContactMenuItem = menu.add(0, MENU_ADD_CONTACTS, 0, R.string.recentCalls_addToContact)
.setIcon(android.R.drawable.ic_menu_add);
m2SecPauseMenuItem = menu.add(0, MENU_2S_PAUSE, 0, R.string.add_2sec_pause)
.setIcon(R.drawable.ic_menu_2sec_pause);
mWaitMenuItem = menu.add(0, MENU_WAIT, 0, R.string.add_wait)
.setIcon(R.drawable.ic_menu_wait);
- return true;
}
@Override
- public boolean onPrepareOptionsMenu(Menu menu) {
+ public void onPrepareOptionsMenu(Menu menu) {
+ // If we have not been inflated yet, there is no menu
+ if (mDialpadChooser == null) return;
+
// We never show a menu if the "choose dialpad" UI is up.
- if (dialpadChooserVisible()) {
- return false;
- }
+ // Otherwise the menu is allowed (see onPrepareOptionsMenu() below.)
+ if (!dialpadChooserVisible()) return;
if (isDigitsEmpty()) {
mAddToContactMenuItem.setVisible(false);
@@ -587,46 +574,6 @@
strLength, strDigits));
}
}
- return true;
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL: {
- long callPressDiff = SystemClock.uptimeMillis() - event.getDownTime();
- if (callPressDiff >= ViewConfiguration.getLongPressTimeout()) {
- // Launch voice dialer
- Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- startActivity(intent);
- } catch (ActivityNotFoundException e) {
- }
- }
- return true;
- }
- case KeyEvent.KEYCODE_1: {
- long timeDiff = SystemClock.uptimeMillis() - event.getDownTime();
- if (timeDiff >= ViewConfiguration.getLongPressTimeout()) {
- // Long press detected, call voice mail
- callVoicemail();
- }
- return true;
- }
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_CALL: {
- dialButtonPressed();
- return true;
- }
- }
- return super.onKeyUp(keyCode, event);
}
private void keyPressed(int keyCode) {
@@ -647,6 +594,7 @@
return false;
}
+ @Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.one: {
@@ -759,10 +707,10 @@
return false;
}
- void callVoicemail() {
+ public void callVoicemail() {
startActivity(newVoicemailIntent());
mDigits.getText().clear(); // TODO: Fix bug 1745781
- finish();
+ getActivity().finish();
}
/**
@@ -784,7 +732,7 @@
* user needs to press the dial button again, to dial it (general
* case described above).
*/
- void dialButtonPressed() {
+ public void dialButtonPressed() {
if (isDigitsEmpty()) { // No number entered.
if (phoneIsCdma() && phoneIsOffhook()) {
// This is really CDMA specific. On GSM is it possible
@@ -809,11 +757,10 @@
startActivity(newDialNumberIntent(number));
mDigits.getText().clear(); // TODO: Fix bug 1745781
- finish();
+ getActivity().finish();
}
}
-
/**
* Plays the specified tone for TONE_LENGTH_MS milliseconds.
*
@@ -834,16 +781,17 @@
// call, rather than keeping a local flag that's updated in
// onResume(), since it's possible to toggle silent mode without
// leaving the current activity (via the ENDCALL-longpress menu.)
- AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ AudioManager audioManager =
+ (AudioManager) getActivity().getSystemService(Context.AUDIO_SERVICE);
int ringerMode = audioManager.getRingerMode();
if ((ringerMode == AudioManager.RINGER_MODE_SILENT)
|| (ringerMode == AudioManager.RINGER_MODE_VIBRATE)) {
return;
}
- synchronized(mToneGeneratorLock) {
+ synchronized (mToneGeneratorLock) {
if (mToneGenerator == null) {
- Log.w(TAG, "playTone: mToneGenerator == null, tone: "+tone);
+ Log.w(TAG, "playTone: mToneGenerator == null, tone: " + tone);
return;
}
@@ -879,7 +827,7 @@
// Instantiate the DialpadChooserAdapter and hook it up to the
// ListView. We do this only once.
if (mDialpadChooserAdapter == null) {
- mDialpadChooserAdapter = new DialpadChooserAdapter(this);
+ mDialpadChooserAdapter = new DialpadChooserAdapter(getActivity());
mDialpadChooser.setAdapter(mDialpadChooserAdapter);
}
} else {
@@ -1049,7 +997,7 @@
// the dialpad chooser is up. In this case we can't show the
// InCallScreen, and there's no point staying here in the Dialer,
// so we just take the user back where he came from...)
- finish();
+ getActivity().finish();
}
/**
@@ -1097,7 +1045,6 @@
return phoneOffhook;
}
-
/**
* Returns true whenever any one of the options from the menu is selected.
* Code changes to support dialpad options
@@ -1131,7 +1078,7 @@
selectionEnd = Math.max(anchor, point);
Editable digits = mDigits.getText();
- if (selectionStart != -1 ) {
+ if (selectionStart != -1) {
if (selectionStart == selectionEnd) {
// then there is no selection. So insert the pause at this
// position and update the mDigits.
@@ -1171,7 +1118,6 @@
mDelete.setEnabled(digitsNotEmpty);
}
-
/**
* Check if voicemail is enabled/accessible.
*/
@@ -1202,7 +1148,7 @@
if (start > digits.length()) return false;
// preceding char is ';', so visible should be false
- if (digits.charAt(start-1) == ';') return false;
+ if (digits.charAt(start - 1) == ';') return false;
// next char is ';', so visible should be false
if ((digits.length() > start) && (digits.charAt(start) == ';')) return false;
@@ -1212,7 +1158,7 @@
// In this case we need to just check for ';' preceding to start
// or next to end
- if (digits.charAt(start-1) == ';') return false;
+ if (digits.charAt(start - 1) == ';') return false;
}
return true;
}
@@ -1234,7 +1180,7 @@
mLastNumberDialed = EMPTY_NUMBER;
CallLogAsync.GetLastOutgoingCallArgs lastCallArgs =
new CallLogAsync.GetLastOutgoingCallArgs(
- this,
+ getActivity(),
new CallLogAsync.OnLastOutgoingCallComplete() {
public void lastOutgoingCall(String number) {
// TODO: Filter out emergency numbers if
@@ -1247,16 +1193,6 @@
mCallLog.getLastOutgoingCall(lastCallArgs);
}
- @Override
- public void startSearch(String initialQuery, boolean selectInitialQuery, Bundle appSearchData,
- boolean globalSearch) {
- if (globalSearch) {
- super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
- } else {
- ContactsSearchManager.startSearch(this, initialQuery);
- }
- }
-
// Helpers for the call intents.
private Intent newVoicemailIntent() {
final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
diff --git a/src/com/android/contacts/editor/BaseRawContactEditorView.java b/src/com/android/contacts/editor/BaseRawContactEditorView.java
index 49ca863..38636f7 100644
--- a/src/com/android/contacts/editor/BaseRawContactEditorView.java
+++ b/src/com/android/contacts/editor/BaseRawContactEditorView.java
@@ -49,7 +49,6 @@
private PhotoEditorView mPhoto;
private boolean mHasPhotoEditor = false;
- private View mHeader;
private View mBody;
private View mDivider;
@@ -67,15 +66,8 @@
protected void onFinishInflate() {
super.onFinishInflate();
- mHeader = findViewById(R.id.header);
mBody = findViewById(R.id.body);
mDivider = findViewById(R.id.divider);
- mHeader.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- setExpanded(!mExpanded);
- }
- });
mPhoto = (PhotoEditorView)findViewById(R.id.edit_photo);
mPhoto.setEnabled(isEnabled());
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index ae6788b..96d5843 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -31,6 +31,7 @@
import com.android.contacts.model.EntityDeltaList;
import com.android.contacts.model.EntityModifier;
import com.android.contacts.model.GoogleAccountType;
+import com.android.contacts.util.AccountsListAdapter;
import android.accounts.Account;
import android.app.Activity;
@@ -78,7 +79,9 @@
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.ViewStub;
+import android.widget.AdapterView;
import android.widget.LinearLayout;
+import android.widget.ListPopupWindow;
import android.widget.Toast;
import java.io.File;
@@ -90,7 +93,7 @@
import java.util.List;
public class ContactEditorFragment extends Fragment implements
- SplitContactConfirmationDialogFragment.Listener, SelectAccountDialogFragment.Listener,
+ SplitContactConfirmationDialogFragment.Listener,
AggregationSuggestionEngine.Listener, AggregationSuggestionView.Listener,
ExternalRawContactEditorView.Listener {
@@ -313,7 +316,7 @@
} else {
// No Account specified. Let the user choose
// Load Accounts async so that we can present them
- selectAccountAndCreateContact();
+ createContact();
}
} else if (ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(mAction)) {
// do nothing
@@ -437,7 +440,11 @@
}
}
- private void selectAccountAndCreateContact() {
+ /**
+ * Shows the account creation screen. An account associated with the contact is automatically
+ * selected. If there's no available account, device-local contact should be created.
+ */
+ private void createContact() {
final ArrayList<Account> accounts =
AccountTypeManager.getInstance(mContext).getAccounts(true);
// No Accounts available. Create a phone-local contact.
@@ -446,21 +453,16 @@
return; // Don't show a dialog.
}
- // In the common case of a single account being writable, auto-select
- // it without showing a dialog.
- if (accounts.size() == 1) {
- createContact(accounts.get(0));
- return; // Don't show a dialog.
- }
-
- final SelectAccountDialogFragment dialog = new SelectAccountDialogFragment();
- dialog.setTargetFragment(this, 0);
- dialog.show(getFragmentManager(), SelectAccountDialogFragment.TAG);
+ // We have an account switcher in "create-account" screen, so don't need to ask a user to
+ // select an account here.
+ createContact(accounts.get(0));
}
+
/**
- * @param account may be null to signal a device-local contact should
- * be created.
+ * Shows account creation screen associated with a given account.
+ *
+ * @param account may be null to signal a device-local contact should be created.
*/
private void createContact(Account account) {
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
@@ -476,31 +478,66 @@
}
}
+ /**
+ * Removes a current editor ({@link #mState}) and rebinds new editor for a new account.
+ * Some of old data are reused with new restriction enforced by the new account.
+ *
+ * @param oldState Old data being editted.
+ * @param oldAccount Old account associated with oldState.
+ * @param newAccount New account to be used.
+ */
+ private void rebindEditorsForNewContact(
+ EntityDelta oldState, Account oldAccount, Account newAccount) {
+ AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
+ AccountType oldAccountType = accountTypes.getAccountType(oldAccount.type);
+ AccountType newAccountType = accountTypes.getAccountType(newAccount.type);
+
+ if (newAccountType.getCreateContactActivityClassName() != null) {
+ Log.w(TAG, "external activity called in rebind situation");
+ if (mListener != null) {
+ mListener.onCustomCreateContactActivityRequested(newAccount, mIntentExtras);
+ }
+ } else {
+ mState = null;
+ bindEditorsForNewContact(newAccount, newAccountType, oldState, oldAccountType);
+ }
+ }
+
private void bindEditorsForNewContact(Account account, final AccountType accountType) {
+ bindEditorsForNewContact(account, accountType, null, null);
+ }
+
+ private void bindEditorsForNewContact(Account newAccount, final AccountType newAccountType,
+ EntityDelta oldState, AccountType oldAccountType) {
mStatus = Status.EDITING;
final ContentValues values = new ContentValues();
- if (account != null) {
- values.put(RawContacts.ACCOUNT_NAME, account.name);
- values.put(RawContacts.ACCOUNT_TYPE, account.type);
+ if (newAccount != null) {
+ values.put(RawContacts.ACCOUNT_NAME, newAccount.name);
+ values.put(RawContacts.ACCOUNT_TYPE, newAccount.type);
} else {
values.putNull(RawContacts.ACCOUNT_NAME);
values.putNull(RawContacts.ACCOUNT_TYPE);
}
- // Parse any values from incoming intent
EntityDelta insert = new EntityDelta(ValuesDelta.fromAfter(values));
- EntityModifier.parseExtras(mContext, accountType, insert, mIntentExtras);
+ if (oldState == null) {
+ // Parse any values from incoming intent
+ EntityModifier.parseExtras(mContext, newAccountType, insert, mIntentExtras);
+ } else {
+ EntityModifier.migrateStateForNewContact(mContext, oldState, insert,
+ oldAccountType, newAccountType);
+ }
// Ensure we have some default fields (if the account type does not support a field,
// ensureKind will not add it, so it is safe to add e.g. Event)
- EntityModifier.ensureKindExists(insert, accountType, Phone.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, Email.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, Note.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, Organization.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, Event.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, Website.CONTENT_ITEM_TYPE);
- EntityModifier.ensureKindExists(insert, accountType, StructuredPostal.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Phone.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Email.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Note.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Organization.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Event.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, Website.CONTENT_ITEM_TYPE);
+ EntityModifier.ensureKindExists(insert, newAccountType, StructuredPostal.CONTENT_ITEM_TYPE);
if (mState == null) {
// Create state if none exists yet
@@ -545,6 +582,13 @@
editor = (BaseRawContactEditorView)
inflater.inflate(R.layout.raw_contact_editor_view, mContent, false);
}
+ if (Intent.ACTION_INSERT.equals(mAction) && size == 1) {
+ final ArrayList<Account> accounts =
+ AccountTypeManager.getInstance(mContext).getAccounts(true);
+ if (accounts.size() > 1) {
+ addAccountSwitcher(mState.get(0), editor);
+ }
+ }
editor.setEnabled(mEnabled);
mContent.addView(editor);
@@ -613,6 +657,40 @@
}
}
+ private void addAccountSwitcher(
+ final EntityDelta currentState, BaseRawContactEditorView editor) {
+ ValuesDelta values = currentState.getValues();
+ final Account currentAccount = new Account(
+ values.getAsString(RawContacts.ACCOUNT_NAME),
+ values.getAsString(RawContacts.ACCOUNT_TYPE));
+ final View accountView = editor.findViewById(R.id.account);
+ final View anchorView = editor.findViewById(R.id.anchor_for_account_switcher);
+ accountView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final ListPopupWindow popup = new ListPopupWindow(mContext, null);
+ final AccountsListAdapter adapter = new AccountsListAdapter(mContext, true);
+ popup.setWidth(anchorView.getWidth());
+ popup.setAnchorView(anchorView);
+ popup.setAdapter(adapter);
+ popup.setModal(true);
+ popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
+ popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position,
+ long id) {
+ popup.dismiss();
+ Account newAccount = adapter.getItem(position);
+ if (!newAccount.equals(currentAccount)) {
+ rebindEditorsForNewContact(currentState, currentAccount, newAccount);
+ }
+ }
+ });
+ popup.show();
+ }
+ });
+ }
+
@Override
public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.edit, menu);
@@ -980,11 +1058,6 @@
void onContactSplit(Uri newLookupUri);
/**
- * User was presented with an account selection and couldn't decide.
- */
- void onAccountSelectorAborted();
-
- /**
* User has tapped Revert, close the fragment now.
*/
void onReverted();
@@ -1538,24 +1611,6 @@
save(SaveMode.SPLIT);
}
- /**
- * Account was chosen in the selector. Create a RawContact for this account now
- */
- @Override
- public void onAccountChosen(Account account) {
- createContact(account);
- }
-
- /**
- * The account selector has been aborted. If we are in "New" mode, we have to close now
- */
- @Override
- public void onAccountSelectorCancelled() {
- if (!hasValidState() && mListener != null) {
- mListener.onAccountSelectorAborted();
- }
- }
-
private final class PhotoEditorListener
implements EditorListener, PhotoActionPopup.Listener {
private final BaseRawContactEditorView mEditor;
diff --git a/src/com/android/contacts/editor/Editor.java b/src/com/android/contacts/editor/Editor.java
index d733e68..a70bf3f 100644
--- a/src/com/android/contacts/editor/Editor.java
+++ b/src/com/android/contacts/editor/Editor.java
@@ -16,8 +16,8 @@
package com.android.contacts.editor;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import android.provider.ContactsContract.Data;
@@ -27,9 +27,7 @@
* {@link ValuesDelta} object.
*/
public interface Editor {
- /**
- * Listener for an {@link Editor}, usually to handle deleted items.
- */
+
public interface EditorListener {
/**
* Called when the given {@link Editor} has been deleted.
@@ -44,14 +42,21 @@
public static final int REQUEST_PICK_PHOTO = 1;
public static final int FIELD_CHANGED = 2;
+ public static final int FIELD_TURNED_EMPTY = 3;
+ public static final int FIELD_TURNED_NON_EMPTY = 4;
// The editor has switched between different representations of the same
// data, e.g. from full name to structured name
- public static final int EDITOR_FORM_CHANGED = 3;
+ public static final int EDITOR_FORM_CHANGED = 5;
}
/**
- * Prepare this editor for the given {@link ValuesDelta}, which
+ * Returns whether or not all the fields are empty in this {@link Editor}.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Prepares this editor for the given {@link ValuesDelta}, which
* builds any needed views. Any changes performed by the user will be
* written back to that same object.
*/
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index 906dbad..bf93d26 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -20,9 +20,9 @@
import com.android.contacts.datepicker.DatePicker;
import com.android.contacts.datepicker.DatePickerDialog;
import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditField;
import com.android.contacts.model.AccountType.EventEditType;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.util.DateUtils;
@@ -32,10 +32,8 @@
import android.os.Bundle;
import android.text.TextUtils;
import android.util.AttributeSet;
-import android.view.Gravity;
import android.view.View;
import android.widget.Button;
-import android.widget.LinearLayout;
import java.text.ParsePosition;
import java.util.Calendar;
@@ -49,7 +47,7 @@
/**
* Exchange requires 8:00 for birthdays
*/
- private final int DEFAULT_HOUR = 8;
+ private final static int DEFAULT_HOUR = 8;
private Button mDateView;
@@ -65,57 +63,30 @@
super(context, attrs, defStyle);
}
+ /** {@inheritDoc} */
@Override
- public int getBaseline(int row) {
- int baseline = super.getBaseline(row);
- if (mDateView != null) {
- // The date view will be centered vertically in the corresponding line item
- int lineItemHeight = getLineItemHeight(row);
- int offset = (lineItemHeight - mDateView.getMeasuredHeight()) / 2;
- baseline = Math.max(baseline, offset + mDateView.getBaseline());
- }
- return baseline;
- }
+ protected void onFinishInflate() {
+ super.onFinishInflate();
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- int l1 = getPaddingLeft();
- int t1 = getPaddingTop();
- int r1 = getMeasuredWidth() - getPaddingRight();
-
- // Fields
- // Subtract buttons left and right if necessary
- final int labelWidth = (getLabel() != null) ? getLabel().getMeasuredWidth() : 0;
- final int deleteWidth = (getDelete() != null) ? getDelete().getMeasuredWidth() : 0;
- final int r2 = r1 - deleteWidth - labelWidth;
- if (mDateView != null) {
- int height = mDateView.getMeasuredHeight();
- int baseline = getBaseline(0);
- int top = t1 + baseline - mDateView.getBaseline();
- mDateView.layout(
- l1, top,
- r2, top + height);
- }
- }
-
- @Override
- protected int getLineItemHeight(int row) {
- int height = mDateView == null ? 0 : mDateView.getMeasuredHeight();
- return Math.max(height, super.getLineItemHeight(row));
+ mDateView = (Button) findViewById(R.id.date_view);
+ mDateView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showDialog(R.id.dialog_event_date_picker);
+ }
+ });
}
@Override
protected void requestFocusForFirstEditField() {
- if (mDateView != null) mDateView.requestFocus();
+ mDateView.requestFocus();
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
- if (mDateView != null) mDateView.setEnabled(!isReadOnly() && enabled);
+ mDateView.setEnabled(!isReadOnly() && enabled);
}
@Override
@@ -124,20 +95,7 @@
if (kind.fieldList.size() != 1) throw new IllegalStateException("kind must have 1 field");
super.setValues(kind, entry, state, readOnly, vig);
- if (mDateView == null) {
-
- mDateView = new Button(getContext(), null, android.R.attr.spinnerStyle);
- mDateView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.WRAP_CONTENT));
- mDateView.setEnabled(isEnabled() && !readOnly);
- mDateView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- showDialog(R.id.dialog_event_date_picker);
- }
- });
- addView(mDateView);
- }
+ mDateView.setEnabled(isEnabled() && !readOnly);
rebuildDateView();
}
@@ -153,6 +111,11 @@
}
@Override
+ public boolean isEmpty() {
+ return TextUtils.isEmpty(mDateView.getText());
+ }
+
+ @Override
public Dialog createDialog(Bundle bundle) {
if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
int dialogId = bundle.getInt(DIALOG_ID_KEY);
@@ -269,4 +232,11 @@
oldYear, oldMonth, oldDay, isYearOptional);
return resultDialog;
}
+
+ /**
+ * @return Default hour which should be used for birthday field.
+ */
+ public static int getDefaultHourForBirthday() {
+ return DEFAULT_HOUR;
+ }
}
diff --git a/src/com/android/contacts/editor/ExternalRawContactEditorView.java b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
index aaa1e44..89cace0 100644
--- a/src/com/android/contacts/editor/ExternalRawContactEditorView.java
+++ b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
@@ -20,7 +20,7 @@
import com.android.contacts.R;
import com.android.contacts.editor.ExternalRawContactEditorView.Listener;
import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityModifier;
@@ -60,9 +60,9 @@
private Button mEditExternallyButton;
private ViewGroup mGeneral;
- private ImageView mHeaderIcon;
- private TextView mHeaderAccountType;
- private TextView mHeaderAccountName;
+ private ImageView mAccountIcon;
+ private TextView mAccountTypeTextView;
+ private TextView mAccountNameTextView;
private String mAccountName;
private String mAccountType;
@@ -102,9 +102,9 @@
mEditExternallyButton.setOnClickListener(this);
mGeneral = (ViewGroup)findViewById(R.id.sect_general);
- mHeaderIcon = (ImageView) findViewById(R.id.header_icon);
- mHeaderAccountType = (TextView) findViewById(R.id.header_account_type);
- mHeaderAccountName = (TextView) findViewById(R.id.header_account_name);
+ mAccountIcon = (ImageView) findViewById(R.id.account_icon);
+ mAccountTypeTextView = (TextView) findViewById(R.id.account_type);
+ mAccountNameTextView = (TextView) findViewById(R.id.account_name);
}
/**
@@ -132,11 +132,11 @@
accountType = mContext.getString(R.string.account_phone);
}
if (!TextUtils.isEmpty(mAccountName)) {
- mHeaderAccountName.setText(
+ mAccountNameTextView.setText(
mContext.getString(R.string.from_account_format, mAccountName));
}
- mHeaderAccountType.setText(mContext.getString(R.string.account_type_format, accountType));
- mHeaderIcon.setImageDrawable(type.getDisplayIcon(mContext));
+ mAccountTypeTextView.setText(mContext.getString(R.string.account_type_format, accountType));
+ mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext));
mRawContactId = values.getAsLong(RawContacts._ID);
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index 8845aa3..d242a1b 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -19,7 +19,7 @@
import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
import com.android.contacts.interactions.GroupCreationDialogFragment;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityModifier;
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index aaeafac..b472279 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -18,23 +18,22 @@
import com.android.contacts.R;
import com.android.contacts.editor.Editor.EditorListener;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityModifier;
import android.content.Context;
-import android.os.Handler;
-import android.provider.ContactsContract.Data;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
+import java.util.List;
/**
* Custom view for an entire section of data as segmented by
@@ -45,9 +44,8 @@
private static final String TAG = "KindSectionView";
private ViewGroup mEditors;
- private View mAddPlusButtonContainer;
- private ImageButton mAddPlusButton;
- private TextView mTitle;
+ private View mAddFieldFooter;
+ private TextView mAddFieldText;
private String mTitleString;
private DataKind mKind;
@@ -56,7 +54,7 @@
private ViewIdGenerator mViewIdGenerator;
- private int mMinLineItemHeight;
+ private LayoutInflater mInflater;
public KindSectionView(Context context) {
this(context, null);
@@ -64,8 +62,6 @@
public KindSectionView(Context context, AttributeSet attrs) {
super(context, attrs);
- mMinLineItemHeight = context.getResources().getDimensionPixelSize(
- R.dimen.editor_min_line_item_height);
}
@Override
@@ -78,26 +74,13 @@
}
}
- if (mAddPlusButton != null) {
- mAddPlusButton.setEnabled(enabled && !mReadOnly);
+ if (enabled && !mReadOnly) {
+ mAddFieldFooter.setVisibility(View.VISIBLE);
+ } else {
+ mAddFieldFooter.setVisibility(View.GONE);
}
}
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- if (mAddPlusButton == null || mEditors == null || mEditors.getChildCount() < 2) {
- return;
- }
-
- // Align the "+" button with the "-" button in the last editor
- View lastEditor = mEditors.getChildAt(mEditors.getChildCount() - 1);
- int top = lastEditor.getTop();
- mAddPlusButtonContainer.layout(mAddPlusButtonContainer.getLeft(), top,
- mAddPlusButtonContainer.getRight(), top + mAddPlusButtonContainer.getHeight());
- }
-
public boolean isReadOnly() {
return mReadOnly;
}
@@ -108,37 +91,36 @@
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
- mEditors = (ViewGroup)findViewById(R.id.kind_editors);
+ mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mAddPlusButtonContainer = findViewById(R.id.kind_plus_container);
- mAddPlusButton = (ImageButton) findViewById(R.id.kind_plus);
- mAddPlusButton.setOnClickListener(new OnClickListener() {
+ mEditors = (ViewGroup)findViewById(R.id.kind_editors);
+ mAddFieldText = (TextView) findViewById(R.id.add_text);
+ mAddFieldFooter = findViewById(R.id.add_field_footer);
+ mAddFieldFooter.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- // defer action so that the pressed state of the button is visible shortly
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- addItem();
- }
- });
+ // Setup click listener to add an empty field when the footer is clicked.
+ mAddFieldFooter.setVisibility(View.GONE);
+ addItem();
}
});
-
- mTitle = (TextView)findViewById(R.id.kind_title);
}
/** {@inheritDoc} */
@Override
public void onDeleted(Editor editor) {
- updateAddVisible();
- updateVisible();
+ updateAddFooterVisible();
+ updateSectionVisible();
}
/** {@inheritDoc} */
@Override
public void onRequest(int request) {
- // Ignore requests
+ // If a field has become empty or non-empty, then check if another row
+ // can be added dynamically.
+ if (request == FIELD_TURNED_EMPTY || request == FIELD_TURNED_NON_EMPTY) {
+ updateAddFooterVisible();
+ }
}
public void setState(DataKind kind, EntityDelta state, boolean readOnly, ViewIdGenerator vig) {
@@ -153,11 +135,17 @@
mTitleString = (kind.titleRes == -1 || kind.titleRes == 0)
? ""
: getResources().getString(kind.titleRes);
- mTitle.setText(mTitleString);
+
+ // Set "add field" footer message according to MIME type. Some MIME types
+ // can only have max 1 field, so the resource ID will be -1 if these sections
+ // should not have an "Add field" option.
+ if (kind.addNewFieldTextResourceId != -1) {
+ mAddFieldText.setText(getResources().getString(kind.addNewFieldTextResourceId));
+ }
rebuildFromState();
- updateAddVisible();
- updateVisible();
+ updateAddFooterVisible();
+ updateSectionVisible();
}
public String getTitle() {
@@ -193,16 +181,13 @@
*/
private View createEditorView(ValuesDelta entry) {
final View view;
- if (mKind.editorClass == null) {
- view = new TextFieldsEditorView(mContext);
- } else {
- try {
- view = mKind.editorClass.getConstructor(Context.class).newInstance(
- mContext);
- } catch (Exception e) {
- throw new RuntimeException(
- "Cannot allocate editor for " + mKind.editorClass);
- }
+ try {
+ view = mInflater.inflate(mKind.editorLayoutResourceId, mEditors, false);
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Cannot allocate editor with layout resource ID " +
+ mKind.editorLayoutResourceId + " for MIME type " + mKind.mimeType +
+ " with error " + e.toString());
}
view.setEnabled(isEnabled());
@@ -231,26 +216,68 @@
return true;
}
- private void updateVisible() {
+ private void updateSectionVisible() {
setVisibility(getEditorCount() != 0 ? VISIBLE : GONE);
}
-
- protected void updateAddVisible() {
- final boolean isVisible;
- if (!mKind.isList) {
- isVisible = false;
- } else {
- // Set enabled state on the "add" view
- final boolean canInsert = EntityModifier.canInsert(mState, mKind);
- isVisible = !mReadOnly && canInsert;
+ protected void updateAddFooterVisible() {
+ if (!mReadOnly && mKind.isList) {
+ // First determine whether there are any existing empty editors.
+ updateEmptyEditors();
+ // If there are no existing empty editors and it's possible to add
+ // another field, then make the "add footer" field visible.
+ if (!hasEmptyEditor() && EntityModifier.canInsert(mState, mKind)) {
+ mAddFieldFooter.setVisibility(View.VISIBLE);
+ return;
+ }
}
- mAddPlusButton.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
+ mAddFieldFooter.setVisibility(View.GONE);
+ }
+
+ /**
+ * Updates the editors being displayed to the user removing extra empty
+ * {@link Editor}s, so there is only max 1 empty {@link Editor} view at a time.
+ */
+ private void updateEmptyEditors() {
+ List<View> emptyEditors = getEmptyEditors();
+
+ // If there is more than 1 empty editor, then remove it from the list of editors.
+ if (emptyEditors.size() > 1) {
+ for (View emptyEditorView : emptyEditors) {
+ // If no child {@link View}s are being focused on within
+ // this {@link View}, then remove this empty editor.
+ if (emptyEditorView.findFocus() == null) {
+ mEditors.removeView(emptyEditorView);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a list of empty editor views in this section.
+ */
+ private List<View> getEmptyEditors() {
+ List<View> emptyEditorViews = new ArrayList<View>();
+ for (int i = 0; i < mEditors.getChildCount(); i++) {
+ View view = mEditors.getChildAt(i);
+ if (((Editor) view).isEmpty()) {
+ emptyEditorViews.add(view);
+ }
+ }
+ return emptyEditorViews;
+ }
+
+ /**
+ * Returns true if one of the editors has all of its fields empty, or false
+ * otherwise.
+ */
+ private boolean hasEmptyEditor() {
+ return getEmptyEditors().size() > 0;
}
public void addItem() {
ValuesDelta values = null;
- // if this is a list, we can freely add. if not, only allow adding the first
+ // If this is a list, we can freely add. If not, only allow adding the first.
if (!mKind.isList) {
if (getEditorCount() == 1) {
return;
@@ -277,12 +304,11 @@
}
});
- // For non-lists (e.g. Notes we can only have one field. in that case we need to disable
- // the add button
- updateAddVisible();
+ // Hide the "add field" footer because there is now a blank field.
+ mAddFieldFooter.setVisibility(View.GONE);
// Ensure we are visible
- updateVisible();
+ updateSectionVisible();
}
public int getEditorCount() {
diff --git a/src/com/android/contacts/editor/LabeledEditorView.java b/src/com/android/contacts/editor/LabeledEditorView.java
index a6815a7..af5ae65 100644
--- a/src/com/android/contacts/editor/LabeledEditorView.java
+++ b/src/com/android/contacts/editor/LabeledEditorView.java
@@ -18,21 +18,19 @@
import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityModifier;
import com.android.contacts.util.DialogManager;
import com.android.contacts.util.DialogManager.DialogShowingView;
-import com.android.contacts.util.ThemeUtils;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Entity;
-import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
@@ -45,32 +43,36 @@
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
-import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.List;
/**
- * Base class for editors that handles labels and values.
- * Uses {@link ValuesDelta} to read any existing
- * {@link Entity} values, and to correctly write any changes values.
+ * Base class for editors that handles labels and values. Uses
+ * {@link ValuesDelta} to read any existing {@link Entity} values, and to
+ * correctly write any changes values.
*/
-public abstract class LabeledEditorView extends ViewGroup implements Editor, DialogShowingView {
+public abstract class LabeledEditorView extends LinearLayout implements Editor, DialogShowingView {
protected static final String DIALOG_ID_KEY = "dialog_id";
private static final int DIALOG_ID_CUSTOM = 1;
private static final int INPUT_TYPE_CUSTOM = EditorInfo.TYPE_CLASS_TEXT
| EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS;
+ private TextView mTitle;
private Spinner mLabel;
private EditTypeAdapter mEditTypeAdapter;
- private ImageButton mDelete;
+ private View mDeleteContainer;
+ private ImageView mDelete;
private DataKind mKind;
private ValuesDelta mEntry;
private EntityDelta mState;
private boolean mReadOnly;
+ private boolean mWasEmpty = true;
private EditType mType;
@@ -117,6 +119,39 @@
R.dimen.editor_min_line_item_height);
}
+ /** {@inheritDoc} */
+ @Override
+ protected void onFinishInflate() {
+
+ mTitle = (TextView) findViewById(R.id.title);
+
+ mLabel = (Spinner) findViewById(R.id.spinner);
+ mLabel.setOnItemSelectedListener(mSpinnerListener);
+
+ mDelete = (ImageView) findViewById(R.id.delete_button);
+ mDeleteContainer = findViewById(R.id.delete_button_container);
+ mDeleteContainer.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // defer removal of this button so that the pressed state is visible shortly
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ // Keep around in model, but mark as deleted
+ mEntry.markDeleted();
+
+ ((ViewGroup) getParent()).removeView(LabeledEditorView.this);
+
+ if (mListener != null) {
+ // Notify listener when present
+ mListener.onDeleted(LabeledEditorView.this);
+ }
+ }
+ });
+ }
+ });
+ }
+
public boolean isReadOnly() {
return mReadOnly;
}
@@ -129,96 +164,21 @@
}
/**
- * Returns the number of rows in this editor, including the invisible ones.
- */
- protected int getLineItemCount() {
- return 1;
- }
-
- protected boolean isLineItemVisible(int row) {
- return true;
- }
-
- protected int getLineItemHeight(int row) {
- int fieldHeight = 0;
- int buttonHeight = 0;
- if (row == 0) {
- // summarize the EditText heights
- if (mLabel != null) {
- fieldHeight = mLabel.getMeasuredHeight();
- }
-
- // Ensure there is enough space for the minus button
- View deleteButton = getDelete();
- final int deleteHeight = (deleteButton != null) ? deleteButton.getMeasuredHeight() : 0;
- buttonHeight += deleteHeight;
- }
-
- return Math.max(Math.max(buttonHeight, fieldHeight), mMinLineItemHeight);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- measureChildren(widthMeasureSpec, heightMeasureSpec);
-
- int height = 0;
- height += getPaddingTop() + getPaddingBottom();
-
- int count = getLineItemCount();
- for (int i = 0; i < count; i++) {
- if (isLineItemVisible(i)) {
- height += getLineItemHeight(i);
- }
- }
-
- setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
- resolveSize(height, heightMeasureSpec));
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- // Subtract padding from the borders ==> x1 variables
- int t1 = getPaddingTop();
- int r1 = getMeasuredWidth() - getPaddingRight();
- int b1 = getMeasuredHeight() - getPaddingBottom();
-
- final int r2;
- if (mDelete != null) {
- r2 = r1 - mDelete.getMeasuredWidth();
- // Vertically center the delete button in the first line item
- int height = mDelete.getMeasuredHeight();
- int top = t1 + (mMinLineItemHeight - height) / 2;
- mDelete.layout(
- r2, top,
- r1, top + height);
- } else {
- r2 = r1;
- }
-
- if (mLabel != null) {
- int baseline = getBaseline(0);
- int y = t1 + baseline - mLabel.getBaseline();
- mLabel.layout(
- r2 - mLabel.getMeasuredWidth(), y,
- r2, y + mLabel.getMeasuredHeight());
- }
- }
-
- /**
* Creates or removes the type/label button. Doesn't do anything if already correctly configured
*/
private void setupLabelButton(boolean shouldExist) {
- if (shouldExist && mLabel == null) {
- mLabel = new Spinner(mContext);
- final int width =
- mContext.getResources().getDimensionPixelSize(R.dimen.editor_type_label_width);
- mLabel.setLayoutParams(new LayoutParams(width, LayoutParams.WRAP_CONTENT));
- mLabel.setOnItemSelectedListener(mSpinnerListener);
+ if (mTitle == null) {
+ return;
+ }
+ if (shouldExist) {
mLabel.setEnabled(!mReadOnly && isEnabled());
- addView(mLabel);
- } else if (!shouldExist && mLabel != null) {
- removeView(mLabel);
- mLabel = null;
+ mLabel.setVisibility(View.VISIBLE);
+
+ // Since there's a spinner for this editor, use this as the title
+ // instead of the title TextView.
+ mTitle.setVisibility(View.GONE);
+ } else {
+ mLabel.setVisibility(View.GONE);
}
}
@@ -226,46 +186,11 @@
* Creates or removes the remove button. Doesn't do anything if already correctly configured
*/
private void setupDeleteButton(boolean shouldExist) {
- if (shouldExist && mDelete == null) {
- mDelete = new ImageButton(mContext);
- mDelete.setImageResource(R.drawable.ic_menu_remove_field_holo_light);
- mDelete.setBackgroundResource(
- ThemeUtils.getSelectableItemBackground(mContext.getTheme()));
- final Resources resources = mContext.getResources();
- mDelete.setPadding(
- resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_left),
- resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_top),
- resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_right),
- resources.getDimensionPixelOffset(R.dimen.editor_round_button_padding_bottom));
- mDelete.setContentDescription(
- getResources().getText(R.string.description_minus_button));
- mDelete.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- mDelete.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // defer removal of this button so that the pressed state is visible shortly
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- // Keep around in model, but mark as deleted
- mEntry.markDeleted();
-
- ((ViewGroup) getParent()).removeView(LabeledEditorView.this);
-
- if (mListener != null) {
- // Notify listener when present
- mListener.onDeleted(LabeledEditorView.this);
- }
- }
- });
- }
- });
+ if (shouldExist) {
+ mDeleteContainer.setVisibility(View.VISIBLE);
mDelete.setEnabled(!mReadOnly && isEnabled());
- addView(mDelete);
- } else if (!shouldExist && mDelete != null) {
- removeView(mDelete);
- mDelete = null;
+ } else {
+ mDeleteContainer.setVisibility(View.GONE);
}
}
@@ -288,15 +213,15 @@
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
- if (mLabel != null) mLabel.setEnabled(!mReadOnly && enabled);
- if (mDelete != null) mDelete.setEnabled(!mReadOnly && enabled);
+ mLabel.setEnabled(!mReadOnly && enabled);
+ mDelete.setEnabled(!mReadOnly && enabled);
}
public Spinner getLabel() {
return mLabel;
}
- public ImageButton getDelete() {
+ public ImageView getDelete() {
return mDelete;
}
@@ -317,7 +242,6 @@
* possible custom label string.
*/
private void rebuildLabel() {
- if (mLabel == null) return;
mEditTypeAdapter = new EditTypeAdapter(mContext);
mLabel.setAdapter(mEditTypeAdapter);
if (mEditTypeAdapter.hasCustomSelection()) {
@@ -338,6 +262,16 @@
if (mListener != null) {
mListener.onRequest(EditorListener.FIELD_CHANGED);
}
+
+ boolean isEmpty = isEmpty();
+ if (mWasEmpty != isEmpty) {
+ if (isEmpty) {
+ mListener.onRequest(EditorListener.FIELD_TURNED_EMPTY);
+ } else {
+ mListener.onRequest(EditorListener.FIELD_TURNED_NON_EMPTY);
+ }
+ mWasEmpty = isEmpty;
+ }
}
protected boolean isFieldChanged(String column, String value) {
@@ -374,10 +308,22 @@
}
setVisibility(View.VISIBLE);
+ // TODO: handle resources from remote packages
+ String titleString = (kind.titleRes == -1 || kind.titleRes == 0)
+ ? ""
+ : getResources().getString(kind.titleRes);
+
+ // If there is a title field, then setup the title (although it may not be shown if there is
+ // a Spinner setup later). There are cases where a title may not be present (i.e. structured
+ // name).
+ if (mTitle != null) {
+ mTitle.setText(titleString.toUpperCase());
+ }
+
// Display label selector if multiple types available
final boolean hasTypes = EntityModifier.hasEditTypes(kind);
setupLabelButton(hasTypes);
- if (mLabel != null) mLabel.setEnabled(!readOnly && isEnabled());
+ mLabel.setEnabled(!readOnly && isEnabled());
if (hasTypes) {
mType = EntityModifier.getCurrentType(entry, kind);
rebuildLabel();
@@ -556,7 +502,7 @@
} else {
text = getContext().getString(type.labelRes);
}
- textView.setText(text);
+ textView.setText(text.toUpperCase());
return view;
}
}
diff --git a/src/com/android/contacts/editor/PhoneticNameEditorView.java b/src/com/android/contacts/editor/PhoneticNameEditorView.java
index d3aa00d..cfc9b13 100644
--- a/src/com/android/contacts/editor/PhoneticNameEditorView.java
+++ b/src/com/android/contacts/editor/PhoneticNameEditorView.java
@@ -16,10 +16,11 @@
package com.android.contacts.editor;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
+import android.content.ContentValues;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;
@@ -60,55 +61,20 @@
}
private void parsePhoneticName(String value) {
- String family = null;
- String middle = null;
- String given = null;
-
- if (!TextUtils.isEmpty(value)) {
- String[] strings = value.split(" ", 3);
- switch (strings.length) {
- case 1:
- family = strings[0];
- break;
- case 2:
- family = strings[0];
- given = strings[1];
- break;
- case 3:
- family = strings[0];
- middle = strings[1];
- given = strings[2];
- break;
- }
- }
-
- mValues.put(StructuredName.PHONETIC_FAMILY_NAME, family);
- mValues.put(StructuredName.PHONETIC_MIDDLE_NAME, middle);
- mValues.put(StructuredName.PHONETIC_GIVEN_NAME, given);
+ ContentValues values = PhoneticNameEditorView.parsePhoneticName(value, null);
+ mValues.put(StructuredName.PHONETIC_FAMILY_NAME,
+ values.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
+ mValues.put(StructuredName.PHONETIC_MIDDLE_NAME,
+ values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME));
+ mValues.put(StructuredName.PHONETIC_GIVEN_NAME,
+ values.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
}
private void buildPhoneticName() {
String family = mValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME);
String middle = mValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME);
String given = mValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME);
-
- if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
- || !TextUtils.isEmpty(given)) {
- StringBuilder sb = new StringBuilder();
- if (!TextUtils.isEmpty(family)) {
- sb.append(family.trim()).append(' ');
- }
- if (!TextUtils.isEmpty(middle)) {
- sb.append(middle.trim()).append(' ');
- }
- if (!TextUtils.isEmpty(given)) {
- sb.append(given.trim()).append(' ');
- }
- sb.setLength(sb.length() - 1); // Yank the last space
- mPhoneticName = sb.toString();
- } else {
- mPhoneticName = null;
- }
+ mPhoneticName = PhoneticNameEditorView.buildPhoneticName(family, middle, given);
}
@Override
@@ -122,6 +88,73 @@
}
}
+ /**
+ * Parses phonetic name and returns parsed data (family, middle, given) as ContentValues.
+ * Parsed data should be {@link StructuredName#PHONETIC_FAMILY_NAME},
+ * {@link StructuredName#PHONETIC_MIDDLE_NAME}, and
+ * {@link StructuredName#PHONETIC_GIVEN_NAME}.
+ * If this method cannot parse given phoneticName, null values will be stored.
+ *
+ * @param phoneticName Phonetic name to be parsed
+ * @param values ContentValues to be used for storing data. If null, new instance will be
+ * created.
+ * @return ContentValues with parsed data. Those data can be null.
+ */
+ public static ContentValues parsePhoneticName(String phoneticName, ContentValues values) {
+ String family = null;
+ String middle = null;
+ String given = null;
+
+ if (!TextUtils.isEmpty(phoneticName)) {
+ String[] strings = phoneticName.split(" ", 3);
+ switch (strings.length) {
+ case 1:
+ family = strings[0];
+ break;
+ case 2:
+ family = strings[0];
+ given = strings[1];
+ break;
+ case 3:
+ family = strings[0];
+ middle = strings[1];
+ given = strings[2];
+ break;
+ }
+ }
+
+ if (values == null) {
+ values = new ContentValues();
+ }
+ values.put(StructuredName.PHONETIC_FAMILY_NAME, family);
+ values.put(StructuredName.PHONETIC_MIDDLE_NAME, middle);
+ values.put(StructuredName.PHONETIC_GIVEN_NAME, given);
+ return values;
+ }
+
+ /**
+ * Constructs and returns a phonetic full name from given parts.
+ */
+ public static String buildPhoneticName(String family, String middle, String given) {
+ if (!TextUtils.isEmpty(family) || !TextUtils.isEmpty(middle)
+ || !TextUtils.isEmpty(given)) {
+ StringBuilder sb = new StringBuilder();
+ if (!TextUtils.isEmpty(family)) {
+ sb.append(family.trim()).append(' ');
+ }
+ if (!TextUtils.isEmpty(middle)) {
+ sb.append(middle.trim()).append(' ');
+ }
+ if (!TextUtils.isEmpty(given)) {
+ sb.append(given.trim()).append(' ');
+ }
+ sb.setLength(sb.length() - 1); // Yank the last space
+ return sb.toString();
+ } else {
+ return null;
+ }
+ }
+
public PhoneticNameEditorView(Context context) {
super(context);
}
diff --git a/src/com/android/contacts/editor/PhotoEditorView.java b/src/com/android/contacts/editor/PhotoEditorView.java
index 89633fd..7b86291 100644
--- a/src/com/android/contacts/editor/PhotoEditorView.java
+++ b/src/com/android/contacts/editor/PhotoEditorView.java
@@ -17,8 +17,8 @@
package com.android.contacts.editor;
import com.android.contacts.R;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import android.content.Context;
@@ -178,4 +178,9 @@
public void setDeletable(boolean deletable) {
// Photo is not deletable
}
+
+ @Override
+ public boolean isEmpty() {
+ return !mHasSetPhoto;
+ }
}
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index 633b343..5ef2c21 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -19,12 +19,14 @@
import com.android.contacts.GroupMetaDataLoader;
import com.android.contacts.R;
import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityModifier;
+import android.accounts.Account;
import android.content.Context;
import android.content.Entity;
import android.database.Cursor;
@@ -68,9 +70,10 @@
private ViewGroup mFields;
- private ImageView mHeaderIcon;
- private TextView mHeaderAccountType;
- private TextView mHeaderAccountName;
+ private View mAccountContainer;
+ private ImageView mAccountIcon;
+ private TextView mAccountTypeTextView;
+ private TextView mAccountNameTextView;
private Button mAddFieldButton;
@@ -130,16 +133,16 @@
final int photoSize = getResources().getDimensionPixelSize(R.dimen.edit_photo_size);
mName = (StructuredNameEditorView)findViewById(R.id.edit_name);
- mName.setMinimumHeight(photoSize);
mName.setDeletable(false);
mPhoneticName = (PhoneticNameEditorView)findViewById(R.id.edit_phonetic_name);
mFields = (ViewGroup)findViewById(R.id.sect_fields);
- mHeaderIcon = (ImageView) findViewById(R.id.header_icon);
- mHeaderAccountType = (TextView) findViewById(R.id.header_account_type);
- mHeaderAccountName = (TextView) findViewById(R.id.header_account_name);
+ mAccountContainer = findViewById(R.id.account);
+ mAccountIcon = (ImageView) findViewById(R.id.account_icon);
+ mAccountTypeTextView = (TextView) findViewById(R.id.account_type);
+ mAccountNameTextView = (TextView) findViewById(R.id.account_name);
mAddFieldButton = (Button) findViewById(R.id.button_add_field);
mAddFieldButton.setOnClickListener(new OnClickListener() {
@@ -170,29 +173,36 @@
// Make sure we have StructuredName
EntityModifier.ensureKindExists(state, type, StructuredName.CONTENT_ITEM_TYPE);
- // Fill in the header info
ValuesDelta values = state.getValues();
- String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
- CharSequence accountType = type.getDisplayLabel(mContext);
- if (TextUtils.isEmpty(accountType)) {
- accountType = mContext.getString(R.string.account_phone);
- }
- if (!TextUtils.isEmpty(accountName)) {
- mHeaderAccountName.setText(
- mContext.getString(R.string.from_account_format, accountName));
- }
- mHeaderAccountType.setText(mContext.getString(R.string.account_type_format, accountType));
- mHeaderIcon.setImageDrawable(type.getDisplayIcon(mContext));
-
mRawContactId = values.getAsLong(RawContacts._ID);
+ final ArrayList<Account> accounts =
+ AccountTypeManager.getInstance(mContext).getAccounts(true);
+ if (accounts.size() > 1) {
+ // Fill in the account info
+ String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
+ CharSequence accountType = type.getDisplayLabel(mContext);
+ if (TextUtils.isEmpty(accountType)) {
+ accountType = mContext.getString(R.string.account_phone);
+ }
+ if (!TextUtils.isEmpty(accountName)) {
+ mAccountNameTextView.setText(
+ mContext.getString(R.string.from_account_format, accountName));
+ }
+ mAccountTypeTextView.setText(
+ mContext.getString(R.string.account_type_format, accountType));
+ mAccountIcon.setImageDrawable(type.getDisplayIcon(mContext));
+ } else {
+ mAccountContainer.setVisibility(View.GONE);
+ }
+
// Show photo editor when supported
EntityModifier.ensureKindExists(state, type, Photo.CONTENT_ITEM_TYPE);
setHasPhotoEditor((type.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null));
getPhotoEditor().setEnabled(isEnabled());
mName.setEnabled(isEnabled());
- mName.setEditorTextSize(
- mContext.getResources().getDimensionPixelSize(R.dimen.contact_name_text_size));
+ mName.setEditorTextSize(mContext.getResources().getDimensionPixelSize(
+ R.dimen.editor_structured_name_text_size));
mPhoneticName.setEnabled(isEnabled());
diff --git a/src/com/android/contacts/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
index 67c5f6e..65370f5 100644
--- a/src/com/android/contacts/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/editor/SelectAccountDialogFragment.java
@@ -53,8 +53,7 @@
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
- final Listener target = (Listener) getTargetFragment();
- target.onAccountChosen(accountAdapter.getItem(which));
+ onAccountSelected(accountAdapter.getItem(which));
}
};
@@ -67,12 +66,27 @@
@Override
public void onCancel(DialogInterface dialog) {
super.onCancel(dialog);
- final Listener target = (Listener) getTargetFragment();
- target.onAccountSelectorCancelled();
+ final Fragment targetFragment = getTargetFragment();
+ if (targetFragment != null && targetFragment instanceof Listener) {
+ final Listener target = (Listener) targetFragment;
+ target.onAccountSelectorCancelled();
+ }
+ }
+
+ /**
+ * Calls {@link Listener#onAccountChosen(int, Account)} if the target fragment is castable
+ * to {@link Listener}. Subclasses can also overide to directly perform an operation
+ */
+ protected void onAccountSelected(Account account) {
+ final Fragment targetFragment = getTargetFragment();
+ if (targetFragment != null && targetFragment instanceof Listener) {
+ final Listener target = (Listener) targetFragment;
+ target.onAccountChosen(getTargetRequestCode(), account);
+ }
}
public interface Listener {
- void onAccountChosen(Account account);
+ void onAccountChosen(int requestCode, Account account);
void onAccountSelectorCancelled();
}
}
diff --git a/src/com/android/contacts/editor/StructuredNameEditorView.java b/src/com/android/contacts/editor/StructuredNameEditorView.java
index cf97c6c..5a2ffd3 100644
--- a/src/com/android/contacts/editor/StructuredNameEditorView.java
+++ b/src/com/android/contacts/editor/StructuredNameEditorView.java
@@ -16,22 +16,23 @@
package com.android.contacts.editor;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
+import com.android.contacts.util.NameConverter;
import android.content.ContentValues;
import android.content.Context;
-import android.database.Cursor;
import android.net.Uri;
-import android.net.Uri.Builder;
import android.os.Parcel;
import android.os.Parcelable;
-import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;
import android.util.AttributeSet;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* A dedicated editor for structured name. When the user collapses/expands
* the structured name, it will reparse or recompose the name, but only
@@ -107,41 +108,20 @@
ValuesDelta values = getValues();
if (!mChanged) {
- values.put(StructuredName.PREFIX,
- mSnapshot.getAsString(StructuredName.PREFIX));
- values.put(StructuredName.GIVEN_NAME,
- mSnapshot.getAsString(StructuredName.GIVEN_NAME));
- values.put(StructuredName.MIDDLE_NAME,
- mSnapshot.getAsString(StructuredName.MIDDLE_NAME));
- values.put(StructuredName.FAMILY_NAME,
- mSnapshot.getAsString(StructuredName.FAMILY_NAME));
- values.put(StructuredName.SUFFIX,
- mSnapshot.getAsString(StructuredName.SUFFIX));
+ for (String field : NameConverter.STRUCTURED_NAME_FIELDS) {
+ values.put(field, mSnapshot.getAsString(field));
+ }
return;
}
String displayName = values.getAsString(StructuredName.DISPLAY_NAME);
- Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
- appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName);
- Cursor cursor = getContext().getContentResolver().query(builder.build(), new String[]{
- StructuredName.PREFIX,
- StructuredName.GIVEN_NAME,
- StructuredName.MIDDLE_NAME,
- StructuredName.FAMILY_NAME,
- StructuredName.SUFFIX,
- }, null, null, null);
-
- try {
- if (cursor.moveToFirst()) {
- eraseFullName(values);
- values.put(StructuredName.PREFIX, cursor.getString(0));
- values.put(StructuredName.GIVEN_NAME, cursor.getString(1));
- values.put(StructuredName.MIDDLE_NAME, cursor.getString(2));
- values.put(StructuredName.FAMILY_NAME, cursor.getString(3));
- values.put(StructuredName.SUFFIX, cursor.getString(4));
+ Map<String, String> structuredNameMap = NameConverter.displayNameToStructuredName(
+ getContext(), displayName);
+ if (!structuredNameMap.isEmpty()) {
+ eraseFullName(values);
+ for (String field : structuredNameMap.keySet()) {
+ values.put(field, structuredNameMap.get(field));
}
- } finally {
- cursor.close();
}
mSnapshot.clear();
@@ -158,39 +138,27 @@
return;
}
- String prefix = values.getAsString(StructuredName.PREFIX);
- String givenName = values.getAsString(StructuredName.GIVEN_NAME);
- String middleName = values.getAsString(StructuredName.MIDDLE_NAME);
- String familyName = values.getAsString(StructuredName.FAMILY_NAME);
- String suffix = values.getAsString(StructuredName.SUFFIX);
-
- Uri.Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath(
- "complete_name");
- appendQueryParameter(builder, StructuredName.PREFIX, prefix);
- appendQueryParameter(builder, StructuredName.GIVEN_NAME, givenName);
- appendQueryParameter(builder, StructuredName.MIDDLE_NAME, middleName);
- appendQueryParameter(builder, StructuredName.FAMILY_NAME, familyName);
- appendQueryParameter(builder, StructuredName.SUFFIX, suffix);
- Cursor cursor = getContext().getContentResolver().query(builder.build(), new String[]{
- StructuredName.DISPLAY_NAME,
- }, null, null, null);
-
- try {
- if (cursor.moveToFirst()) {
- eraseStructuredName(values);
- values.put(StructuredName.DISPLAY_NAME, cursor.getString(0));
- }
- } finally {
- cursor.close();
+ Map<String, String> structuredNameMap = valuesToStructuredNameMap(values);
+ String displayName = NameConverter.structuredNameToDisplayName(getContext(),
+ structuredNameMap);
+ if (!TextUtils.isEmpty(displayName)) {
+ eraseStructuredName(values);
+ values.put(StructuredName.DISPLAY_NAME, displayName);
}
mSnapshot.clear();
mSnapshot.put(StructuredName.DISPLAY_NAME, values.getAsString(StructuredName.DISPLAY_NAME));
- mSnapshot.put(StructuredName.PREFIX, prefix);
- mSnapshot.put(StructuredName.GIVEN_NAME, givenName);
- mSnapshot.put(StructuredName.MIDDLE_NAME, middleName);
- mSnapshot.put(StructuredName.FAMILY_NAME, familyName);
- mSnapshot.put(StructuredName.SUFFIX, suffix);
+ for (String field : structuredNameMap.keySet()) {
+ mSnapshot.put(field, structuredNameMap.get(field));
+ }
+ }
+
+ private Map<String, String> valuesToStructuredNameMap(ValuesDelta values) {
+ Map<String, String> structuredNameMap = new HashMap<String, String>();
+ for (String key : NameConverter.STRUCTURED_NAME_FIELDS) {
+ structuredNameMap.put(key, values.getAsString(key));
+ }
+ return structuredNameMap;
}
private void eraseFullName(ValuesDelta values) {
@@ -198,14 +166,12 @@
}
private void eraseStructuredName(ValuesDelta values) {
- values.putNull(StructuredName.PREFIX);
- values.putNull(StructuredName.GIVEN_NAME);
- values.putNull(StructuredName.MIDDLE_NAME);
- values.putNull(StructuredName.FAMILY_NAME);
- values.putNull(StructuredName.SUFFIX);
+ for (String field : NameConverter.STRUCTURED_NAME_FIELDS) {
+ values.putNull(field);
+ }
}
- private void appendQueryParameter(Uri.Builder builder, String field, String value) {
+ private static void appendQueryParameter(Uri.Builder builder, String field, String value) {
if (!TextUtils.isEmpty(value)) {
builder.appendQueryParameter(field, value);
}
diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java
index 031ab18..04a9485 100644
--- a/src/com/android/contacts/editor/TextFieldsEditorView.java
+++ b/src/com/android/contacts/editor/TextFieldsEditorView.java
@@ -18,40 +18,49 @@
import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditField;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.android.contacts.util.ThemeUtils;
+import com.android.contacts.util.NameConverter;
import android.content.Context;
import android.content.Entity;
-import android.content.res.Resources;
import android.graphics.Rect;
+import android.graphics.Typeface;
import android.os.Parcel;
import android.os.Parcelable;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.telephony.PhoneNumberFormattingTextWatcher;
import android.text.Editable;
import android.text.InputType;
+import android.text.Spannable;
+import android.text.TextUtils;
import android.text.TextWatcher;
+import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.EditText;
-import android.widget.ImageButton;
+import android.widget.ImageView;
import android.widget.LinearLayout;
+import java.util.Map;
+
/**
- * Simple editor that handles labels and any {@link EditField} defined for
- * the entry. Uses {@link ValuesDelta} to read any existing
- * {@link Entity} values, and to correctly write any changes values.
+ * Simple editor that handles labels and any {@link EditField} defined for the
+ * entry. Uses {@link ValuesDelta} to read any existing {@link Entity} values,
+ * and to correctly write any changes values.
*/
public class TextFieldsEditorView extends LabeledEditorView {
private EditText[] mFieldEditTexts = null;
- private ImageButton mMoreOrLess;
+ private ViewGroup mFields = null;
+ private View mExpansionViewContainer;
+ private ImageView mExpansionView;
private boolean mHideOptional = true;
private boolean mHasShortAndLongForms;
- private int mEditorTextSize;
+ private int mEditorTextSize = 0;
public TextFieldsEditorView(Context context) {
super(context);
@@ -65,97 +74,46 @@
super(context, attrs, defStyle);
}
- public void setEditorTextSize(int textSize) {
- this.mEditorTextSize = textSize;
- }
-
+ /** {@inheritDoc} */
@Override
- protected int getLineItemCount() {
- int count = mFieldEditTexts == null ? 0 : mFieldEditTexts.length;
- return Math.max(count, super.getLineItemCount());
- }
+ protected void onFinishInflate() {
+ super.onFinishInflate();
- @Override
- protected boolean isLineItemVisible(int row) {
- return mFieldEditTexts != null && mFieldEditTexts[row].getVisibility() != View.GONE;
- }
+ setDrawingCacheEnabled(true);
+ setAlwaysDrawnWithCacheEnabled(true);
- @Override
- public int getBaseline(int row) {
- int baseline = super.getBaseline(row);
- if (mFieldEditTexts != null) {
- EditText editText = mFieldEditTexts[row];
- // The text field will be centered vertically in the corresponding line item
- int lineItemHeight = getLineItemHeight(row);
- int offset = (lineItemHeight - editText.getMeasuredHeight()) / 2;
- baseline = Math.max(baseline, offset + editText.getBaseline());
- }
- return baseline;
- }
+ mFields = (ViewGroup) findViewById(R.id.editors);
+ mExpansionView = (ImageView) findViewById(R.id.expansion_view);
+ mExpansionViewContainer = findViewById(R.id.expansion_view_container);
+ mExpansionViewContainer.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // Save focus
+ final View focusedChild = getFocusedChild();
+ final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
+ // Reconfigure GUI
+ mHideOptional = !mHideOptional;
+ onOptionalFieldVisibilityChange();
+ rebuildValues();
- int l1 = getPaddingLeft();
- int t1 = getPaddingTop();
- int r1 = getMeasuredWidth() - getPaddingRight();
-
- if ((mMoreOrLess != null)) {
- mMoreOrLess.layout(
- r1 - mMoreOrLess.getMeasuredWidth(), t1,
- r1, t1 + mMoreOrLess.getMeasuredHeight());
- }
-
- // Subtract buttons if necessary
- final int labelWidth = (getLabel() != null) ? getLabel().getMeasuredWidth() : 0;
- final int deleteWidth = (getDelete() != null) ? getDelete().getMeasuredWidth() : 0;
- final int moreOrLessWidth = mMoreOrLess != null ? mMoreOrLess.getMeasuredWidth() : 0;
- final int r2 = r1 - Math.max(deleteWidth, moreOrLessWidth) - labelWidth;
-
- // Layout text fields
- int y = t1;
- if (mFieldEditTexts != null) {
- for (int i = 0; i < mFieldEditTexts.length; i++) {
- int baseline = getBaseline(i);
- EditText editText = mFieldEditTexts[i];
- if (editText.getVisibility() != View.GONE) {
- int height = editText.getMeasuredHeight();
- int top = t1 + y + baseline - editText.getBaseline();
- editText.layout(
- l1, top,
- r2, top + height);
- y += getLineItemHeight(i);
+ // Restore focus
+ View newFocusView = findViewById(focusedViewId);
+ if (newFocusView == null || newFocusView.getVisibility() == GONE) {
+ // find first visible child
+ newFocusView = TextFieldsEditorView.this;
}
+ newFocusView.requestFocus();
}
- }
+ });
}
- @Override
- protected int getLineItemHeight(int row) {
- int fieldHeight = 0;
- int buttonHeight = 0;
-
- boolean lastLineItem = true;
- if (mFieldEditTexts != null) {
- fieldHeight = mFieldEditTexts[row].getMeasuredHeight();
- lastLineItem = (row == mFieldEditTexts.length - 1);
- }
-
- // Ensure there is enough space for the more/less button
- if (row == 0) {
- final int moreOrLessHeight = mMoreOrLess != null ? mMoreOrLess.getMeasuredHeight() : 0;
- buttonHeight += moreOrLessHeight;
- }
-
- // Ensure there is enough space for the minus button
- if (lastLineItem) {
- View deleteButton = getDelete();
- final int deleteHeight = (deleteButton != null) ? deleteButton.getMeasuredHeight() : 0;
- buttonHeight += deleteHeight;
- }
-
- return Math.max(Math.max(buttonHeight, fieldHeight), super.getLineItemHeight(row));
+ /**
+ * Set the text size of the value of all fields in this class, which will override the default
+ * text appearance style for the associated {@link DataKind}.
+ */
+ public void setEditorTextSize(int textSize) {
+ mEditorTextSize = textSize;
}
@Override
@@ -167,59 +125,20 @@
mFieldEditTexts[index].setEnabled(!isReadOnly() && enabled);
}
}
- if (mMoreOrLess != null) mMoreOrLess.setEnabled(!isReadOnly() && enabled);
+ mExpansionView.setEnabled(!isReadOnly() && enabled);
}
/**
* Creates or removes the type/label button. Doesn't do anything if already correctly configured
*/
- private void setupMoreOrLessButton(boolean shouldExist, boolean collapsed) {
+ private void setupExpansionView(boolean shouldExist, boolean collapsed) {
if (shouldExist) {
- if (mMoreOrLess == null) {
- mMoreOrLess = new ImageButton(mContext);
- mMoreOrLess.setBackgroundResource(
- ThemeUtils.getSelectableItemBackground(mContext.getTheme()));
- final Resources resources = mContext.getResources();
- mMoreOrLess.setPadding(
- resources.getDimensionPixelOffset(
- R.dimen.editor_round_button_padding_left),
- resources.getDimensionPixelOffset(
- R.dimen.editor_round_button_padding_top),
- resources.getDimensionPixelOffset(
- R.dimen.editor_round_button_padding_right),
- resources.getDimensionPixelOffset(
- R.dimen.editor_round_button_padding_bottom));
- mMoreOrLess.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- mMoreOrLess.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // Save focus
- final View focusedChild = getFocusedChild();
- final int focusedViewId = focusedChild == null ? -1 : focusedChild.getId();
-
- // Reconfigure GUI
- mHideOptional = !mHideOptional;
- onOptionalFieldVisibilityChange();
- rebuildValues();
-
- // Restore focus
- View newFocusView = findViewById(focusedViewId);
- if (newFocusView == null || newFocusView.getVisibility() == GONE) {
- // find first visible child
- newFocusView = TextFieldsEditorView.this;
- }
- newFocusView.requestFocus();
- }
- });
- addView(mMoreOrLess);
- }
- mMoreOrLess.setImageResource(collapsed
+ mExpansionViewContainer.setVisibility(View.VISIBLE);
+ mExpansionView.setImageResource(collapsed
? R.drawable.ic_menu_expander_minimized_holo_light
: R.drawable.ic_menu_expander_maximized_holo_light);
- } else if (mMoreOrLess != null) {
- removeView(mMoreOrLess);
- mMoreOrLess = null;
+ } else {
+ mExpansionViewContainer.setVisibility(View.GONE);
}
}
@@ -250,7 +169,7 @@
// Remove edit texts that we currently have
if (mFieldEditTexts != null) {
for (EditText fieldEditText : mFieldEditTexts) {
- removeView(fieldEditText);
+ mFields.removeView(fieldEditText);
}
}
boolean hidePossible = false;
@@ -262,10 +181,11 @@
final EditText fieldView = new EditText(mContext);
fieldView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
- fieldView.setGravity(Gravity.TOP);
+ fieldView.setTextAppearance(getContext(), kind.textAppearanceResourceId);
if (mEditorTextSize != 0) {
fieldView.setTextSize(mEditorTextSize);
}
+ fieldView.setGravity(Gravity.TOP);
mFieldEditTexts[index] = fieldView;
fieldView.setId(vig.getId(state, kind, entry, index));
if (field.titleRes > 0) {
@@ -273,6 +193,9 @@
}
int inputType = field.inputType;
fieldView.setInputType(inputType);
+ if (field.isFullName) {
+ fieldView.addTextChangedListener(new NameFormattingTextWatcher());
+ }
if (inputType == InputType.TYPE_CLASS_PHONE) {
fieldView.addTextChangedListener(new PhoneNumberFormattingTextWatcher(
ContactsUtils.getCurrentCountryIso(mContext)));
@@ -319,12 +242,23 @@
hidePossible = hidePossible || couldHide;
}
- addView(fieldView);
+ mFields.addView(fieldView);
}
// When hiding fields, place expandable
- setupMoreOrLessButton(hidePossible, mHideOptional);
- if (mMoreOrLess != null) mMoreOrLess.setEnabled(!readOnly && isEnabled());
+ setupExpansionView(hidePossible, mHideOptional);
+ mExpansionView.setEnabled(!readOnly && isEnabled());
+ }
+
+ @Override
+ public boolean isEmpty() {
+ for (int i = 0; i < mFields.getChildCount(); i++) {
+ EditText editText = (EditText) mFields.getChildAt(i);
+ if (!TextUtils.isEmpty(editText.getText())) {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -424,4 +358,60 @@
}
};
}
+
+ private class NameFormattingTextWatcher implements TextWatcher {
+
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ String displayName = s.toString();
+ Map<String, String> structuredName = NameConverter.displayNameToStructuredName(
+ getContext(), displayName);
+ String givenName = structuredName.get(StructuredName.GIVEN_NAME);
+ if (!TextUtils.isEmpty(givenName)) {
+ int spanStart = -1;
+ int spanEnd = -1;
+ if (displayName.startsWith(givenName + " ")) {
+ spanStart = 0;
+ spanEnd = givenName.length();
+ } else {
+ spanStart = displayName.lastIndexOf(" " + givenName);
+ if (spanStart > -1) {
+ spanStart++;
+ spanEnd = spanStart + givenName.length();
+ }
+ }
+
+ // If the requested range is already bolded, don't make any changes.
+ if (spanStart > -1) {
+ StyleSpan[] existingSpans = s.getSpans(0, s.length(), StyleSpan.class);
+ for (StyleSpan span : existingSpans) {
+ if (span.getStyle() == Typeface.BOLD
+ && s.getSpanStart(span.getUnderlying()) == spanStart
+ && s.getSpanEnd(span.getUnderlying()) == spanEnd) {
+ // Nothing to do - the correct portion is already bolded.
+ return;
+ }
+ }
+
+ // Clear any existing bold style spans.
+ for (StyleSpan span : existingSpans) {
+ if (span.getStyle() == Typeface.BOLD) {
+ s.removeSpan(span);
+ }
+ }
+
+ // Set the new bold span.
+ s.setSpan(new StyleSpan(Typeface.BOLD), spanStart, spanEnd,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ }
+ }
}
diff --git a/src/com/android/contacts/editor/ViewIdGenerator.java b/src/com/android/contacts/editor/ViewIdGenerator.java
index 93bb002..c3cd08b 100644
--- a/src/com/android/contacts/editor/ViewIdGenerator.java
+++ b/src/com/android/contacts/editor/ViewIdGenerator.java
@@ -16,8 +16,8 @@
package com.android.contacts.editor;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import android.os.Bundle;
diff --git a/src/com/android/contacts/format/DisplayNameFormatter.java b/src/com/android/contacts/format/DisplayNameFormatter.java
new file mode 100644
index 0000000..07577f2
--- /dev/null
+++ b/src/com/android/contacts/format/DisplayNameFormatter.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import com.android.contacts.widget.TextWithHighlighting;
+import com.android.contacts.widget.TextWithHighlightingFactory;
+
+import android.database.CharArrayBuffer;
+import android.graphics.Typeface;
+import android.provider.ContactsContract;
+import android.text.Spannable;
+import android.widget.TextView;
+
+/**
+ * Sets the content of the given text view, to contain the formatted display name, with a
+ * prefix if necessary.
+ */
+public final class DisplayNameFormatter {
+ private final CharArrayBuffer mNameBuffer = new CharArrayBuffer(128);
+ private final CharArrayBuffer mAlternateNameBuffer = new CharArrayBuffer(128);
+ private final PrefixHighlighter mPrefixHighlighter;
+
+ private TextWithHighlightingFactory mTextWithHighlightingFactory;
+ private TextWithHighlighting mTextWithHighlighting;
+ private CharSequence mUnknownNameText;
+
+ public DisplayNameFormatter(PrefixHighlighter prefixHighlighter) {
+ mPrefixHighlighter = prefixHighlighter;
+ }
+
+ public CharArrayBuffer getNameBuffer() {
+ return mNameBuffer;
+ }
+
+ public CharArrayBuffer getAlternateNameBuffer() {
+ return mAlternateNameBuffer;
+ }
+
+ public void setTextWithHighlightingFactory(TextWithHighlightingFactory factory) {
+ mTextWithHighlightingFactory = factory;
+ }
+
+ public void setUnknownNameText(CharSequence unknownNameText) {
+ mUnknownNameText = unknownNameText;
+ }
+
+ public void setDisplayName(TextView view, int displayOrder,
+ boolean highlightingEnabled, char[] highlightedPrefix) {
+ view.setText(getDisplayName(displayOrder, highlightingEnabled, highlightedPrefix));
+ }
+
+ public CharSequence getDisplayName(int displayOrder, boolean highlightingEnabled,
+ char[] highlightedPrefix) {
+ // Compute the point at which name and alternate name overlap (for bolding).
+ int overlapPoint = FormatUtils.overlapPoint(mNameBuffer, mAlternateNameBuffer);
+ int boldStart = 0;
+ int boldEnd = overlapPoint;
+ if (displayOrder == ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE) {
+ boldStart = overlapPoint;
+ boldEnd = mNameBuffer.sizeCopied;
+ }
+
+ int size = mNameBuffer.sizeCopied;
+ if (size == 0) {
+ return mUnknownNameText;
+ }
+
+ CharSequence text;
+ if (highlightingEnabled) {
+ if (mTextWithHighlighting == null) {
+ mTextWithHighlighting =
+ mTextWithHighlightingFactory.createTextWithHighlighting();
+ }
+ mTextWithHighlighting.setText(mNameBuffer, mAlternateNameBuffer);
+ text = mTextWithHighlighting;
+ } else {
+ text = FormatUtils.charArrayBufferToString(mNameBuffer);
+ }
+ if (highlightedPrefix != null) {
+ text = mPrefixHighlighter.apply(text, highlightedPrefix);
+ }
+ if (overlapPoint > 0) {
+ // Bold the first or last name.
+ text = FormatUtils.applyStyleToSpan(Typeface.BOLD, text, boldStart, boldEnd,
+ Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ return text;
+ }
+}
diff --git a/src/com/android/contacts/format/FormatUtils.java b/src/com/android/contacts/format/FormatUtils.java
new file mode 100644
index 0000000..34a6078
--- /dev/null
+++ b/src/com/android/contacts/format/FormatUtils.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.format;
+
+import android.database.CharArrayBuffer;
+import android.graphics.Typeface;
+import android.text.SpannableString;
+import android.text.style.StyleSpan;
+
+import java.util.Arrays;
+
+/**
+ * Assorted utility methods related to text formatting in Contacts.
+ */
+public class FormatUtils {
+
+ /**
+ * Finds the earliest point in buffer1 at which the first part of buffer2 matches. For example,
+ * overlapPoint("abcd", "cdef") == 2.
+ */
+ public static int overlapPoint(CharArrayBuffer buffer1, CharArrayBuffer buffer2) {
+ if (buffer1 == null || buffer2 == null) {
+ return -1;
+ }
+ return overlapPoint(Arrays.copyOfRange(buffer1.data, 0, buffer1.sizeCopied),
+ Arrays.copyOfRange(buffer2.data, 0, buffer2.sizeCopied));
+ }
+
+ /**
+ * Finds the earliest point in string1 at which the first part of string2 matches. For example,
+ * overlapPoint("abcd", "cdef") == 2.
+ */
+ public static int overlapPoint(String string1, String string2) {
+ if (string1 == null || string2 == null) {
+ return -1;
+ }
+ return overlapPoint(string1.toCharArray(), string2.toCharArray());
+ }
+
+ /**
+ * Finds the earliest point in array1 at which the first part of array2 matches. For example,
+ * overlapPoint("abcd", "cdef") == 2.
+ */
+ public static int overlapPoint(char[] array1, char[] array2) {
+ if (array1 == null || array2 == null) {
+ return -1;
+ }
+ int count1 = array1.length;
+ int count2 = array2.length;
+
+ // Ignore matching tails of the two arrays.
+ while (count1 > 0 && count2 > 0 && array1[count1 - 1] == array2[count2 - 1]) {
+ count1--;
+ count2--;
+ }
+
+ int size = count2;
+ for (int i = 0; i < count1; i++) {
+ if (i + size > count1) {
+ size = count1 - i;
+ }
+ int j;
+ for (j = 0; j < size; j++) {
+ if (array1[i+j] != array2[j]) {
+ break;
+ }
+ }
+ if (j == size) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Applies the given style to a range of the input CharSequence.
+ * @param style The style to apply (see the style constants in {@link Typeface}).
+ * @param input The CharSequence to style.
+ * @param start Starting index of the range to style (will be clamped to be a minimum of 0).
+ * @param end Ending index of the range to style (will be clamped to a maximum of the input
+ * length).
+ * @param flags Bitmask for configuring behavior of the span. See {@link android.text.Spanned}.
+ * @return The styled CharSequence.
+ */
+ public static CharSequence applyStyleToSpan(int style, CharSequence input, int start, int end,
+ int flags) {
+ // Enforce bounds of the char sequence.
+ start = Math.max(0, start);
+ end = Math.min(input.length(), end);
+ SpannableString text = new SpannableString(input);
+ text.setSpan(new StyleSpan(style), start, end, flags);
+ return text;
+ }
+
+ public static void copyToCharArrayBuffer(String text, CharArrayBuffer buffer) {
+ if (text != null) {
+ char[] data = buffer.data;
+ if (data == null || data.length < text.length()) {
+ buffer.data = text.toCharArray();
+ } else {
+ text.getChars(0, text.length(), data, 0);
+ }
+ buffer.sizeCopied = text.length();
+ } else {
+ buffer.sizeCopied = 0;
+ }
+ }
+
+ /** Returns a String that represents the content of the given {@link CharArrayBuffer}. */
+ public static String charArrayBufferToString(CharArrayBuffer buffer) {
+ return new String(buffer.data, 0, buffer.sizeCopied);
+ }
+
+ /**
+ * Finds the index of the first word that starts with the given prefix.
+ * <p>
+ * If not found, returns -1.
+ *
+ * @param text the text in which to search for the prefix
+ * @param prefix the text to find, in upper case letters
+ */
+ public static int indexOfWordPrefix(CharSequence text, char[] prefix) {
+ int textLength = text.length();
+ int prefixLength = prefix.length;
+
+ if (prefix == null || prefixLength == 0 || textLength < prefixLength) {
+ return -1;
+ }
+
+ int i = 0;
+ while (i < textLength) {
+ // Skip non-word characters
+ while (i < textLength && !Character.isLetterOrDigit(text.charAt(i))) {
+ i++;
+ }
+
+ if (i + prefixLength > textLength) {
+ return -1;
+ }
+
+ // Compare the prefixes
+ int j;
+ for (j = 0; j < prefixLength; j++) {
+ if (Character.toUpperCase(text.charAt(i + j)) != prefix[j]) {
+ break;
+ }
+ }
+ if (j == prefixLength) {
+ return i;
+ }
+
+ // Skip this word
+ while (i < textLength && Character.isLetterOrDigit(text.charAt(i))) {
+ i++;
+ }
+ }
+
+ return -1;
+ }
+}
diff --git a/src/com/android/contacts/format/PrefixHighlighter.java b/src/com/android/contacts/format/PrefixHighlighter.java
new file mode 100644
index 0000000..943dcb4
--- /dev/null
+++ b/src/com/android/contacts/format/PrefixHighlighter.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import android.database.CharArrayBuffer;
+import android.text.SpannableString;
+import android.text.style.ForegroundColorSpan;
+import android.widget.TextView;
+
+/**
+ * Highlights the text in a text field.
+ */
+public class PrefixHighlighter {
+ private final int mPrefixHighlightColor;
+
+ private ForegroundColorSpan mPrefixColorSpan;
+
+ public PrefixHighlighter(int prefixHighlightColor) {
+ mPrefixHighlightColor = prefixHighlightColor;
+ }
+
+ /**
+ * Sets the text on the given text view, highlighting the word that matches the given prefix.
+ *
+ * @param view the view on which to set the text
+ * @param text the string to use as the text
+ * @param prefix the prefix to look for
+ */
+ public void setText(TextView view, String text, char[] prefix) {
+ view.setText(apply(text, prefix));
+ }
+
+ /**
+ * Sets the text on the given text view, highlighting the word that matches the given prefix.
+ *
+ * @param view the view on which to set the text
+ * @param text the text to use as the text
+ * @param prefix the prefix to look for
+ */
+ public void setText(TextView view, CharArrayBuffer text, char[] prefix) {
+ setText(view, FormatUtils.charArrayBufferToString(text), prefix);
+ }
+
+ /**
+ * Returns a CharSequence which highlights the given prefix if found in the given text.
+ *
+ * @param text the text to which to apply the highlight
+ * @param prefix the prefix to look for
+ */
+ public CharSequence apply(CharSequence text, char[] prefix) {
+ int index = FormatUtils.indexOfWordPrefix(text, prefix);
+ if (index != -1) {
+ if (mPrefixColorSpan == null) {
+ mPrefixColorSpan = new ForegroundColorSpan(mPrefixHighlightColor);
+ }
+
+ SpannableString result = new SpannableString(text);
+ result.setSpan(mPrefixColorSpan, index, index + prefix.length, 0 /* flags */);
+ return result;
+ } else {
+ return text;
+ }
+ }
+}
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
new file mode 100644
index 0000000..bccc207
--- /dev/null
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.group;
+
+import com.android.contacts.R;
+import com.android.contacts.GroupMetaData;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * Adapter to populate the list of groups.
+ */
+public class GroupBrowseListAdapter extends BaseAdapter {
+
+ private LayoutInflater mLayoutInflater;
+ private List<GroupMetaData> mGroupList;
+
+ public GroupBrowseListAdapter(Context context, List<GroupMetaData> groupList) {
+ mLayoutInflater = LayoutInflater.from(context);
+ mGroupList = groupList;
+ }
+
+ @Override
+ public int getCount() {
+ return mGroupList.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return getItem(position).getGroupId();
+ }
+
+ @Override
+ public GroupMetaData getItem(int position) {
+ return mGroupList.get(position);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = mLayoutInflater.inflate(R.layout.group_browse_list_item, parent, false);
+ }
+ GroupMetaData group = getItem(position);
+ ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
+ TextView label = (TextView) convertView.findViewById(R.id.label);
+ TextView account = (TextView) convertView.findViewById(R.id.account);
+ icon.setImageResource(R.drawable.ic_menu_display_all_holo_light);
+ label.setText(group.getTitle());
+ account.setText(group.getAccountName());
+
+ // Set the tag to be the GroupMetaData object, in order to extract group attributes from the
+ // view later.
+ convertView.setTag(group);
+ return convertView;
+ }
+
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
new file mode 100644
index 0000000..d9d020e
--- /dev/null
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.group;
+
+import com.android.contacts.GroupMetaData;
+import com.android.contacts.GroupMetaDataLoader;
+import com.android.contacts.R;
+import com.android.contacts.activities.GroupDetailActivity;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.content.Intent;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnFocusChangeListener;
+import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Fragment to display the list of groups.
+ */
+public class GroupBrowseListFragment extends Fragment
+ implements OnFocusChangeListener, OnTouchListener {
+
+ private static final String TAG = "GroupBrowseListFragment";
+
+ private static final int LOADER_GROUPS = 1;
+
+ private Context mContext;
+ private Cursor mGroupListCursor;
+ private List<GroupMetaData> mGroupList = new ArrayList<GroupMetaData>();
+
+ private View mRootView;
+ private ListView mListView;
+ private View mEmptyView;
+
+ public GroupBrowseListFragment() {
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ mRootView = inflater.inflate(R.layout.group_browse_list_fragment, null);
+ mListView = (ListView) mRootView.findViewById(R.id.list);
+ mListView.setOnFocusChangeListener(this);
+ mListView.setOnTouchListener(this);
+ mEmptyView = mRootView.findViewById(R.id.empty);
+ return mRootView;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mContext = activity;
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mContext = null;
+ }
+
+ @Override
+ public void onStart() {
+ getLoaderManager().initLoader(LOADER_GROUPS, null, mGroupLoaderListener);
+ super.onStart();
+ }
+
+ /**
+ * The listener for the group meta data loader.
+ */
+ private final LoaderManager.LoaderCallbacks<Cursor> mGroupLoaderListener =
+ new LoaderCallbacks<Cursor>() {
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ return new GroupMetaDataLoader(mContext);
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mGroupListCursor = data;
+ bindGroupList();
+ }
+
+ public void onLoaderReset(Loader<Cursor> loader) {
+ }
+ };
+
+ private void bindGroupList() {
+ if (mGroupListCursor == null) {
+ return;
+ }
+ mGroupList.clear();
+ mGroupListCursor.moveToPosition(-1);
+ while (mGroupListCursor.moveToNext()) {
+ String accountName = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_NAME);
+ String accountType = mGroupListCursor.getString(GroupMetaDataLoader.ACCOUNT_TYPE);
+ long groupId = mGroupListCursor.getLong(GroupMetaDataLoader.GROUP_ID);
+ String title = mGroupListCursor.getString(GroupMetaDataLoader.TITLE);
+ boolean defaultGroup = mGroupListCursor.isNull(GroupMetaDataLoader.AUTO_ADD)
+ ? false
+ : mGroupListCursor.getInt(GroupMetaDataLoader.AUTO_ADD) != 0;
+ boolean favorites = mGroupListCursor.isNull(GroupMetaDataLoader.FAVORITES)
+ ? false
+ : mGroupListCursor.getInt(GroupMetaDataLoader.FAVORITES) != 0;
+
+ // TODO: Separate groups according to account name and type.
+ mGroupList.add(new GroupMetaData(
+ accountName, accountType, groupId, title, defaultGroup, favorites));
+ }
+
+ mListView.setAdapter(new GroupBrowseListAdapter(mContext, mGroupList));
+ mListView.setEmptyView(mEmptyView);
+ mListView.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ startGroupDetailActivity((GroupMetaData) view.getTag());
+ }
+ });
+ }
+
+ private void startGroupDetailActivity(GroupMetaData group) {
+ if (group == null) {
+ return;
+ }
+ Intent intent = new Intent(mContext, GroupDetailActivity.class);
+ intent.putExtra(GroupDetailActivity.KEY_ACCOUNT_TYPE, group.getAccountType());
+ intent.putExtra(GroupDetailActivity.KEY_ACCOUNT_NAME, group.getAccountName());
+ intent.putExtra(GroupDetailActivity.KEY_GROUP_ID, group.getGroupId());
+ intent.putExtra(GroupDetailActivity.KEY_GROUP_TITLE, group.getTitle());
+ mContext.startActivity(intent);
+ }
+
+ private void hideSoftKeyboard() {
+ if (mContext == null) {
+ return;
+ }
+ // Hide soft keyboard, if visible
+ InputMethodManager inputMethodManager = (InputMethodManager)
+ mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.hideSoftInputFromWindow(mListView.getWindowToken(), 0);
+ }
+
+ /**
+ * Dismisses the soft keyboard when the list takes focus.
+ */
+ @Override
+ public void onFocusChange(View view, boolean hasFocus) {
+ if (view == mListView && hasFocus) {
+ hideSoftKeyboard();
+ }
+ }
+
+ /**
+ * Dismisses the soft keyboard when the list is touched.
+ */
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (view == mListView) {
+ hideSoftKeyboard();
+ }
+ return false;
+ }
+}
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
new file mode 100644
index 0000000..98babac
--- /dev/null
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.contacts.group;
+
+import com.android.contacts.ContactPhotoManager;
+import com.android.contacts.R;
+import com.android.contacts.activities.GroupDetailActivity;
+import com.android.contacts.list.ContactListAdapter;
+import com.android.contacts.list.ContactListFilter;
+import com.android.contacts.list.DefaultContactListAdapter;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.LoaderManager;
+import android.app.LoaderManager.LoaderCallbacks;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.content.Intent;
+import android.content.Loader;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Directory;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ListView;
+
+/**
+ * Displays the details of a group and shows a list of actions possible for the group.
+ */
+public class GroupDetailFragment extends Fragment implements OnScrollListener {
+
+ private static final String TAG = "GroupDetailFragment";
+
+ private static final int LOADER_MEMBERS = 0;
+
+ private Context mContext;
+
+ private View mRootView;
+ private ListView mMemberListView;
+
+ private ContactListAdapter mAdapter;
+ private ContactPhotoManager mPhotoManager;
+
+ public GroupDetailFragment() {
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ mContext = activity;
+ configurePhotoLoader();
+ }
+
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ mContext = null;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ mRootView = inflater.inflate(R.layout.group_detail_fragment, container, false);
+ mMemberListView = (ListView) mRootView.findViewById(R.id.member_list);
+ mMemberListView.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ // TODO: Open contact detail for this person
+ }
+ });
+ return mRootView;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+
+ Intent intent = getActivity().getIntent();
+ String accountType = intent.getStringExtra(GroupDetailActivity.KEY_ACCOUNT_TYPE);
+ String accountName = intent.getStringExtra(GroupDetailActivity.KEY_ACCOUNT_NAME);
+ long groupId = intent.getLongExtra(GroupDetailActivity.KEY_GROUP_ID, -1);
+ String groupTitle = intent.getStringExtra(GroupDetailActivity.KEY_GROUP_TITLE);
+
+ configureAdapter(accountType, accountName, groupId, groupTitle);
+ startGroupMembersLoader();
+ }
+
+ private void configureAdapter(String accountType, String accountName,
+ long groupId, String groupTitle) {
+ mAdapter = new DefaultContactListAdapter(getActivity());
+ mAdapter.setSectionHeaderDisplayEnabled(false);
+ mAdapter.setDisplayPhotos(true);
+ mAdapter.setHasHeader(0, false);
+ mAdapter.setQuickContactEnabled(false);
+ mAdapter.setPinnedPartitionHeadersEnabled(false);
+ mAdapter.setContactNameDisplayOrder(ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+ mAdapter.setSortOrder(ContactsContract.Preferences.SORT_ORDER_PRIMARY);
+ mAdapter.setPhotoLoader(mPhotoManager);
+ mAdapter.setFilter(new ContactListFilter(accountType, accountName, groupId, "", false,
+ groupTitle));
+ mMemberListView.setAdapter(mAdapter);
+ }
+
+ private void configurePhotoLoader() {
+ if (mContext != null) {
+ if (mPhotoManager == null) {
+ mPhotoManager = ContactPhotoManager.getInstance(mContext);
+ }
+ if (mMemberListView != null) {
+ mMemberListView.setOnScrollListener(this);
+ }
+ if (mAdapter != null) {
+ mAdapter.setPhotoLoader(mPhotoManager);
+ }
+ }
+ }
+
+ /**
+ * Start the loader to retrieve the list of group members.
+ */
+ private void startGroupMembersLoader() {
+ getLoaderManager().destroyLoader(LOADER_MEMBERS);
+ getLoaderManager().restartLoader(LOADER_MEMBERS, null, mGroupMemberListLoaderListener);
+ }
+
+ /**
+ * The listener for the group members list loader
+ */
+ private final LoaderManager.LoaderCallbacks<Cursor> mGroupMemberListLoaderListener =
+ new LoaderCallbacks<Cursor>() {
+
+ @Override
+ public CursorLoader onCreateLoader(int id, Bundle args) {
+ CursorLoader loader = new CursorLoader(mContext, null, null, null, null, null);
+ mAdapter.configureLoader(loader, Directory.DEFAULT);
+ return loader;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ mAdapter.changeCursor(loader.getId(), data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {}
+ };
+
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
+ mPhotoManager.pause();
+ } else {
+ mPhotoManager.resume();
+ }
+ }
+}
diff --git a/src/com/android/contacts/interactions/ContactDeletionInteraction.java b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
index 08f8d00..f195c2f 100644
--- a/src/com/android/contacts/interactions/ContactDeletionInteraction.java
+++ b/src/com/android/contacts/interactions/ContactDeletionInteraction.java
@@ -206,8 +206,13 @@
final Uri contactUri = Contacts.getLookupUri(contactId, lookupKey);
showDialog(mMessageId, contactUri);
+
+ // We don't want onLoadFinished() calls any more, which may come when the database is
+ // updating.
+ getLoaderManager().destroyLoader(R.id.dialog_delete_contact_loader_id);
}
+ @Override
public void onLoaderReset(Loader<Cursor> loader) {
}
@@ -235,7 +240,6 @@
public void onDismiss(DialogInterface dialog) {
mActive = false;
mDialog = null;
- getLoaderManager().destroyLoader(R.id.dialog_delete_contact_loader_id);
}
@Override
diff --git a/src/com/android/contacts/interactions/ImportExportInteraction.java b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
similarity index 62%
rename from src/com/android/contacts/interactions/ImportExportInteraction.java
rename to src/com/android/contacts/interactions/ImportExportDialogFragment.java
index bd8ac16..4e22fa2 100644
--- a/src/com/android/contacts/interactions/ImportExportInteraction.java
+++ b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
@@ -17,14 +17,16 @@
package com.android.contacts.interactions;
import com.android.contacts.R;
+import com.android.contacts.editor.SelectAccountDialogFragment;
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.util.AccountSelectionUtil;
import com.android.contacts.vcard.ExportVCardActivity;
import android.accounts.Account;
-import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -35,7 +37,6 @@
import android.provider.ContactsContract.Contacts;
import android.telephony.TelephonyManager;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -46,70 +47,39 @@
import java.util.List;
/**
- * An interaction invoked to import/export contacts.
+ * An dialog invoked to import/export contacts.
*/
-public class ImportExportInteraction {
-
- private static final String TAG = "ImportExportInteraction";
+public class ImportExportDialogFragment extends DialogFragment {
+ public static final String TAG = "ImportExportDialogFragment";
private final String[] LOOKUP_PROJECTION = new String[] {
Contacts.LOOKUP_KEY
};
- private final Context mContext;
-
- public ImportExportInteraction(Context context) {
- this.mContext = context;
+ /** Preferred way to show this dialog */
+ public static void show(FragmentManager fragmentManager) {
+ final ImportExportDialogFragment fragment = new ImportExportDialogFragment();
+ fragment.show(fragmentManager, ImportExportDialogFragment.TAG);
}
- /**
- * Creates a {@link Dialog} that allows the user to choose between a bulk import
- * and bulk export task across all contacts.
- */
- public void startInteraction() {
- showDialog(R.id.dialog_import_export_options, null);
- }
-
- public Dialog onCreateDialog(int id, Bundle bundle) {
- switch (id) {
- case R.id.dialog_import_export_options: {
- return createOptionsDialog();
- }
- case R.string.import_from_sim:
- case R.string.import_from_sdcard: {
- return AccountSelectionUtil.getSelectAccountDialog(mContext, id);
- }
- case R.id.dialog_sdcard_not_found: {
- return new AlertDialog.Builder(mContext)
- .setTitle(R.string.no_sdcard_title)
- .setIconAttribute(android.R.attr.alertDialogIcon)
- .setMessage(R.string.no_sdcard_message)
- .setPositiveButton(android.R.string.ok, null).create();
- }
- }
-
- return null;
- }
-
- private Dialog createOptionsDialog() {
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
// Wrap our context to inflate list items using the correct theme
- final Resources res = mContext.getResources();
- final LayoutInflater dialogInflater = (LayoutInflater)mContext
+ final Resources res = getActivity().getResources();
+ final LayoutInflater dialogInflater = (LayoutInflater)getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Adapter that shows a list of string resources
- final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(mContext,
+ final ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(getActivity(),
android.R.layout.select_dialog_item) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = dialogInflater.inflate(android.R.layout.select_dialog_item,
- parent, false);
- }
+ final TextView result = (TextView)(convertView != null ? convertView :
+ dialogInflater.inflate(android.R.layout.select_dialog_item, parent, false));
- final int resId = this.getItem(position);
- ((TextView)convertView).setText(resId);
- return convertView;
+ final int resId = getItem(position);
+ result.setText(resId);
+ return result;
}
};
@@ -128,6 +98,7 @@
final DialogInterface.OnClickListener clickListener =
new DialogInterface.OnClickListener() {
+ @Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
@@ -139,8 +110,8 @@
break;
}
case R.string.export_to_sdcard: {
- Intent exportIntent = new Intent(mContext, ExportVCardActivity.class);
- mContext.startActivity(exportIntent);
+ Intent exportIntent = new Intent(getActivity(), ExportVCardActivity.class);
+ getActivity().startActivity(exportIntent);
break;
}
case R.string.share_visible_contacts: {
@@ -148,14 +119,13 @@
break;
}
default: {
- Log.e(TAG, "Unexpected resource: " +
- mContext.getResources().getResourceEntryName(resId));
+ Log.e(TAG, "Unexpected resource: "
+ + getActivity().getResources().getResourceEntryName(resId));
}
}
}
};
-
- return new AlertDialog.Builder(mContext)
+ return new AlertDialog.Builder(getActivity())
.setTitle(R.string.dialog_import_export)
.setNegativeButton(android.R.string.cancel, null)
.setSingleChoiceItems(adapter, -1, clickListener)
@@ -163,13 +133,12 @@
}
private void doShareVisibleContacts() {
-
- // TODO move the query into a loader
- final Cursor cursor = mContext.getContentResolver().query(Contacts.CONTENT_URI,
+ // TODO move the query into a loader and do this in a background thread
+ final Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI,
LOOKUP_PROJECTION, Contacts.IN_VISIBLE_GROUP + "!=0", null, null);
try {
if (!cursor.moveToFirst()) {
- Toast.makeText(mContext, R.string.share_error, Toast.LENGTH_SHORT).show();
+ Toast.makeText(getActivity(), R.string.share_error, Toast.LENGTH_SHORT).show();
return;
}
@@ -188,7 +157,7 @@
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(Contacts.CONTENT_VCARD_TYPE);
intent.putExtra(Intent.EXTRA_STREAM, uri);
- mContext.startActivity(intent);
+ getActivity().startActivity(intent);
} finally {
cursor.close();
}
@@ -199,19 +168,37 @@
// - more than one accounts -> ask the user
// - just one account -> use the account without asking the user
// - no account -> use phone-local storage without asking the user
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
final List<Account> accountList = accountTypes.getAccounts(true);
final int size = accountList.size();
if (size > 1) {
- showDialog(resId, null);
+ // Send over to the account selector
+ ImportExportAccountSelectorDialog.show(getFragmentManager(), resId);
return;
}
- AccountSelectionUtil.doImport(mContext, resId, (size == 1 ? accountList.get(0) : null));
+ AccountSelectionUtil.doImport(getActivity(), resId,
+ (size == 1 ? accountList.get(0) : null));
}
- /* Visible for testing */
- void showDialog(int dialogId, Bundle bundle) {
- ((Activity)mContext).showDialog(dialogId, bundle);
+ /** Sub-Dialog for showing an account selector in case there are several accounts */
+ public static class ImportExportAccountSelectorDialog extends SelectAccountDialogFragment {
+ private static final String SELECTOR_TAG = "ImportExportAccountSelectorDialog";
+ private static final String BUNDLE_RES_ID = "resourceId";
+
+ public static void show(FragmentManager manager, int resId) {
+ final ImportExportAccountSelectorDialog dialog =
+ new ImportExportAccountSelectorDialog();
+ final Bundle bundle = new Bundle();
+ bundle.putInt(BUNDLE_RES_ID, resId);
+ dialog.setArguments(bundle);
+ dialog.show(manager, SELECTOR_TAG);
+ }
+
+ @Override
+ protected void onAccountSelected(Account account) {
+ final int resourceId = getArguments().getInt(BUNDLE_RES_ID);
+ AccountSelectionUtil.doImport(getActivity(), resourceId, account);
+ }
}
}
diff --git a/src/com/android/contacts/interactions/PhoneNumberInteraction.java b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
index 277fa56..399b0ea 100644
--- a/src/com/android/contacts/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/contacts/interactions/PhoneNumberInteraction.java
@@ -16,14 +16,19 @@
package com.android.contacts.interactions;
+import com.google.i18n.phonenumbers.NumberParseException;
+import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.i18n.phonenumbers.PhoneNumberUtil.MatchType;
+import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
+
import com.android.contacts.Collapser;
import com.android.contacts.Collapser.Collapsible;
import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.StringInflater;
import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
import android.app.Activity;
import android.app.AlertDialog;
@@ -46,7 +51,7 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
-import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -112,8 +117,16 @@
}
public boolean shouldCollapseWith(PhoneItem phoneItem) {
- if (PhoneNumberUtils.compareStrictly(phoneNumber, phoneItem.phoneNumber)) {
- return true;
+ try {
+ PhoneNumberUtil util = PhoneNumberUtil.getInstance();
+ PhoneNumber phoneNumber1 = util.parse(phoneNumber, "ZZ" /* Unknown */);
+ PhoneNumber phoneNumber2 = util.parse(phoneItem.phoneNumber, "ZZ" /* Unknown */);
+ MatchType matchType = util.isNumberMatch(phoneNumber1, phoneNumber2);
+ if (matchType == MatchType.SHORT_NSN_MATCH) {
+ return true;
+ }
+ } catch (NumberParseException e) {
+ return TextUtils.equals(phoneNumber, phoneItem.phoneNumber);
}
return false;
}
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index be920db..1ecfff1 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -583,7 +583,7 @@
public void viewContact(Uri contactUri) {
setSelectedContactUri(contactUri, false, false, true, false);
- if (mListener != null) { mListener.onViewContactAction(contactUri); }
+ if (mListener != null) mListener.onViewContactAction(contactUri);
}
public void editContact(Uri contactUri) {
diff --git a/src/com/android/contacts/list/ContactEntryListFragment.java b/src/com/android/contacts/list/ContactEntryListFragment.java
index c85f582..fcced62 100644
--- a/src/com/android/contacts/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/list/ContactEntryListFragment.java
@@ -821,6 +821,7 @@
}
}
+ @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
hideSoftKeyboard();
@@ -840,6 +841,7 @@
/**
* Dismisses the soft keyboard when the list takes focus.
*/
+ @Override
public void onFocusChange(View view, boolean hasFocus) {
if (view == mListView && hasFocus) {
hideSoftKeyboard();
@@ -849,6 +851,7 @@
/**
* Dismisses the soft keyboard when the list is touched.
*/
+ @Override
public boolean onTouch(View view, MotionEvent event) {
if (view == mListView) {
hideSoftKeyboard();
diff --git a/src/com/android/contacts/list/ContactListAdapter.java b/src/com/android/contacts/list/ContactListAdapter.java
index cfacc85..2c57983 100644
--- a/src/com/android/contacts/list/ContactListAdapter.java
+++ b/src/com/android/contacts/list/ContactListAdapter.java
@@ -274,8 +274,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, mDisplayNameColumnIndex, isNameHighlightingEnabled(),
- mAlternativeDisplayNameColumnIndex);
+ view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
+ isNameHighlightingEnabled(), getContactNameDisplayOrder());
view.showPhoneticName(cursor, CONTACT_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 116f3f6..bc81cd3 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -18,7 +18,8 @@
import com.android.contacts.ContactPresenceIconUtil;
import com.android.contacts.R;
-import com.android.contacts.widget.TextWithHighlighting;
+import com.android.contacts.format.DisplayNameFormatter;
+import com.android.contacts.format.PrefixHighlighter;
import com.android.contacts.widget.TextWithHighlightingFactory;
import android.content.Context;
@@ -31,10 +32,8 @@
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.provider.ContactsContract.Contacts;
-import android.text.SpannableString;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
-import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -63,12 +62,10 @@
private final int mPaddingRight;
private final int mPaddingBottom;
private final int mPaddingLeft;
- private final int mFadingEdgeLength;
private final int mGapBetweenImageAndText;
private final int mGapBetweenLabelAndData;
private final int mCallButtonPadding;
private final int mPresenceIconMargin;
- private final int mPrefixHightlightColor;
private final int mHeaderTextColor;
private final int mHeaderTextIndent;
private final int mHeaderTextSize;
@@ -110,21 +107,18 @@
private int mLine4Height;
private OnClickListener mCallButtonClickListener;
- private TextWithHighlightingFactory mTextWithHighlightingFactory;
- private CharArrayBuffer mNameBuffer = new CharArrayBuffer(128);
private CharArrayBuffer mDataBuffer = new CharArrayBuffer(128);
- private CharArrayBuffer mHighlightedTextBuffer = new CharArrayBuffer(128);
- private TextWithHighlighting mTextWithHighlighting;
private CharArrayBuffer mPhoneticNameBuffer = new CharArrayBuffer(128);
- private CharSequence mUnknownNameText;
-
private boolean mActivatedStateSupported;
- private ForegroundColorSpan mPrefixColorSpan;
-
private Rect mBoundsWithoutHeader = new Rect();
+ /** A helper used to highlight a prefix in a text field. */
+ private PrefixHighlighter mPrefixHighligher;
+ /** A helper used to format display names. */
+ private DisplayNameFormatter mDisplayNameFormatter;
+
/**
* Special class to allow the parent to be pressed without being pressed itself.
* This way the line of a tab can be pressed, but the image itself is not.
@@ -169,8 +163,6 @@
R.styleable.ContactListItemView_list_item_padding_left, 0);
mPaddingRight = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_padding_right, 0);
- mFadingEdgeLength = a.getDimensionPixelOffset(
- R.styleable.ContactListItemView_list_item_fading_edge_length, 0);
mGapBetweenImageAndText = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_gap_between_image_and_text, 0);
mGapBetweenLabelAndData = a.getDimensionPixelOffset(
@@ -181,9 +173,6 @@
R.styleable.ContactListItemView_list_item_presence_icon_margin, 0);
mDefaultPhotoViewSize = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_photo_size, 0);
- mPrefixHightlightColor = a.getColor(
- R.styleable.ContactListItemView_list_item_prefix_highlight_color, Color.GREEN);
-
mHeaderTextIndent = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_header_text_indent, 0);
mHeaderTextColor = a.getColor(
@@ -191,6 +180,10 @@
mHeaderTextSize = a.getDimensionPixelSize(
R.styleable.ContactListItemView_list_item_header_text_size, 12);
+ mPrefixHighligher = new PrefixHighlighter(
+ a.getColor(R.styleable.ContactListItemView_list_item_prefix_highlight_color,
+ Color.GREEN));
+
a.recycle();
mHeaderBackgroundHeight = mHeaderBackgroundDrawable.getIntrinsicHeight();
@@ -199,6 +192,8 @@
if (mActivatedBackgroundDrawable != null) {
mActivatedBackgroundDrawable.setCallback(this);
}
+
+ mDisplayNameFormatter = new DisplayNameFormatter(mPrefixHighligher);
}
/**
@@ -209,11 +204,11 @@
}
public void setTextWithHighlightingFactory(TextWithHighlightingFactory factory) {
- mTextWithHighlightingFactory = factory;
+ mDisplayNameFormatter.setTextWithHighlightingFactory(factory);
}
public void setUnknownNameText(CharSequence unknownNameText) {
- mUnknownNameText = unknownNameText;
+ mDisplayNameFormatter.setUnknownNameText(unknownNameText);
}
public void setQuickContactEnabled(boolean flag) {
@@ -617,8 +612,6 @@
if (mNameTextView == null) {
mNameTextView = new TextView(mContext);
mNameTextView.setSingleLine(true);
- mNameTextView.setHorizontalFadingEdgeEnabled(true);
- mNameTextView.setFadingEdgeLength(mFadingEdgeLength);
mNameTextView.setEllipsize(getTextEllipsis());
mNameTextView.setTextAppearance(mContext, android.R.style.TextAppearance_Medium);
mNameTextView.setGravity(Gravity.CENTER_VERTICAL);
@@ -674,8 +667,6 @@
if (mPhoneticNameTextView == null) {
mPhoneticNameTextView = new TextView(mContext);
mPhoneticNameTextView.setSingleLine(true);
- mPhoneticNameTextView.setHorizontalFadingEdgeEnabled(true);
- mPhoneticNameTextView.setFadingEdgeLength(mFadingEdgeLength);
mPhoneticNameTextView.setEllipsize(getTextEllipsis());
mPhoneticNameTextView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD);
@@ -721,8 +712,6 @@
if (mLabelView == null) {
mLabelView = new TextView(mContext);
mLabelView.setSingleLine(true);
- mLabelView.setHorizontalFadingEdgeEnabled(true);
- mLabelView.setFadingEdgeLength(mFadingEdgeLength);
mLabelView.setEllipsize(getTextEllipsis());
mLabelView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD);
@@ -754,8 +743,6 @@
if (mDataView == null) {
mDataView = new TextView(mContext);
mDataView.setSingleLine(true);
- mDataView.setHorizontalFadingEdgeEnabled(true);
- mDataView.setFadingEdgeLength(mFadingEdgeLength);
mDataView.setEllipsize(getTextEllipsis());
mDataView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
addView(mDataView);
@@ -772,8 +759,7 @@
mSnippetView.setVisibility(View.GONE);
}
} else {
- getSnippetView();
- setTextWithPrefixHighlighting(mSnippetView, text);
+ mPrefixHighligher.setText(getSnippetView(), text, mHighlightedPrefix);
mSnippetView.setVisibility(VISIBLE);
}
}
@@ -785,8 +771,6 @@
if (mSnippetView == null) {
mSnippetView = new TextView(mContext);
mSnippetView.setSingleLine(true);
- mSnippetView.setHorizontalFadingEdgeEnabled(true);
- mSnippetView.setFadingEdgeLength(mFadingEdgeLength);
mSnippetView.setEllipsize(getTextEllipsis());
mSnippetView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mSnippetView.setTypeface(mSnippetView.getTypeface(), Typeface.BOLD);
@@ -818,28 +802,15 @@
return mActivatedStateSupported ? TruncateAt.START : TruncateAt.MARQUEE;
}
- public void showDisplayName(Cursor cursor, int nameColumnIndex, boolean highlightingEnabled,
- int alternativeNameColumnIndex) {
- cursor.copyStringToBuffer(nameColumnIndex, mNameBuffer);
- TextView nameView = getNameTextView();
- int size = mNameBuffer.sizeCopied;
- if (size != 0) {
- if (mHighlightedPrefix != null) {
- setTextWithPrefixHighlighting(nameView, mNameBuffer);
- } else if (highlightingEnabled) {
- if (mTextWithHighlighting == null) {
- mTextWithHighlighting =
- mTextWithHighlightingFactory.createTextWithHighlighting();
- }
- cursor.copyStringToBuffer(alternativeNameColumnIndex, mHighlightedTextBuffer);
- mTextWithHighlighting.setText(mNameBuffer, mHighlightedTextBuffer);
- nameView.setText(mTextWithHighlighting);
- } else {
- nameView.setText(mNameBuffer.data, 0, size);
- }
- } else {
- nameView.setText(mUnknownNameText);
- }
+ public void showDisplayName(Cursor cursor, int nameColumnIndex, int alternativeNameColumnIndex,
+ boolean highlightingEnabled, int displayOrder) {
+ // Copy out the display name and alternate display name.
+ cursor.copyStringToBuffer(nameColumnIndex, mDisplayNameFormatter.getNameBuffer());
+ cursor.copyStringToBuffer(alternativeNameColumnIndex,
+ mDisplayNameFormatter.getAlternateNameBuffer());
+
+ mDisplayNameFormatter.setDisplayName(
+ getNameTextView(), displayOrder, highlightingEnabled, mHighlightedPrefix);
}
public void showPhoneticName(Cursor cursor, int phoneticNameColumnIndex) {
@@ -924,83 +895,6 @@
this.mActivatedStateSupported = flag;
}
- /**
- * Sets text on the given text view, highlighting the word that matches
- * the given prefix (see {@link #setHighlightedPrefix}).
- */
- private void setTextWithPrefixHighlighting(TextView textView, String text) {
- mHighlightedTextBuffer.sizeCopied =
- Math.min(text.length(), mHighlightedTextBuffer.data.length);
- text.getChars(0, mHighlightedTextBuffer.sizeCopied, mHighlightedTextBuffer.data, 0);
- setTextWithPrefixHighlighting(textView, mHighlightedTextBuffer);
- }
-
- /**
- * Sets text on the given text view, highlighting the word that matches
- * the given prefix (see {@link #setHighlightedPrefix}).
- */
- private void setTextWithPrefixHighlighting(TextView textView, CharArrayBuffer text) {
- int index = indexOfWordPrefix(text, mHighlightedPrefix);
- if (index != -1) {
- if (mPrefixColorSpan == null) {
- mPrefixColorSpan = new ForegroundColorSpan(mPrefixHightlightColor);
- }
-
- String string = new String(text.data, 0, text.sizeCopied);
- SpannableString name = new SpannableString(string);
- name.setSpan(mPrefixColorSpan, index, index + mHighlightedPrefix.length, 0 /* flags */);
- textView.setText(name);
- } else {
- textView.setText(text.data, 0, text.sizeCopied);
- }
- }
-
- /**
- * Finds the index of the word that starts with the given prefix. If not found,
- * returns -1.
- */
- private int indexOfWordPrefix(CharArrayBuffer buffer, char[] prefix) {
- if (prefix == null || prefix.length == 0) {
- return -1;
- }
-
- char[] string1 = buffer.data;
- int count1 = buffer.sizeCopied;
- int count2 = prefix.length;
-
- int size = count2;
- int i = 0;
- while (i < count1) {
-
- // Skip non-word characters
- while (i < count1 && !Character.isLetterOrDigit(string1[i])) {
- i++;
- }
-
- if (i + size > count1) {
- return -1;
- }
-
- // Compare the prefixes
- int j;
- for (j = 0; j < size; j++) {
- if (Character.toUpperCase(string1[i+j]) != prefix[j]) {
- break;
- }
- }
- if (j == size) {
- return i;
- }
-
- // Skip this word
- while (i < count1 && Character.isLetterOrDigit(string1[i])) {
- i++;
- }
- }
-
- return -1;
- }
-
@Override
public void requestLayout() {
// We will assume that once measured this will not need to resize
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index afe29df..3ef68d8 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -27,6 +27,7 @@
import android.provider.Contacts.ContactMethods;
import android.provider.Contacts.People;
import android.provider.Contacts.Phones;
+import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Contacts;
@@ -95,6 +96,8 @@
} else if (ContactMethods.CONTENT_POSTAL_TYPE.equals(resolvedType)) {
request.setActionCode(ContactsRequest.ACTION_PICK_POSTAL);
request.setLegacyCompatibilityMode(true);
+ } else if (Email.CONTENT_TYPE.equals(resolvedType)) {
+ request.setActionCode(ContactsRequest.ACTION_PICK_EMAIL);
}
} else if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
String component = intent.getComponent().getClassName();
diff --git a/src/com/android/contacts/list/ContactsRequest.java b/src/com/android/contacts/list/ContactsRequest.java
index aefa451..e20d189 100644
--- a/src/com/android/contacts/list/ContactsRequest.java
+++ b/src/com/android/contacts/list/ContactsRequest.java
@@ -62,6 +62,9 @@
/** Show all postal addresses and pick them when clicking */
public static final int ACTION_PICK_POSTAL = 100;
+ /** Show all postal addresses and pick them when clicking */
+ public static final int ACTION_PICK_EMAIL = 105;
+
/** Show all contacts and create a shortcut for the picked contact */
public static final int ACTION_CREATE_SHORTCUT_CONTACT = 110;
diff --git a/src/com/android/contacts/list/EmailAddressListAdapter.java b/src/com/android/contacts/list/EmailAddressListAdapter.java
new file mode 100644
index 0000000..eae02b5
--- /dev/null
+++ b/src/com/android/contacts/list/EmailAddressListAdapter.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.CursorLoader;
+import android.database.Cursor;
+import android.net.Uri;
+import android.net.Uri.Builder;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.ContactCounts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * A cursor adapter for the {@link Email#CONTENT_TYPE} content type.
+ */
+public class EmailAddressListAdapter extends ContactEntryListAdapter {
+
+ static final String[] EMAILS_PROJECTION = new String[] {
+ Email._ID, // 0
+ Email.TYPE, // 1
+ Email.LABEL, // 2
+ Email.DATA, // 3
+ Email.DISPLAY_NAME_PRIMARY, // 4
+ Email.DISPLAY_NAME_ALTERNATIVE, // 5
+ Email.PHOTO_ID, // 6
+ };
+
+ protected static final int EMAIL_ID_COLUMN_INDEX = 0;
+ protected static final int EMAIL_TYPE_COLUMN_INDEX = 1;
+ protected static final int EMAIL_LABEL_COLUMN_INDEX = 2;
+ protected static final int EMAIL_ADDRESS_COLUMN_INDEX = 3;
+ protected static final int EMAIL_PRIMARY_DISPLAY_NAME_COLUMN_INDEX = 4;
+ protected static final int EMAIL_ALTERNATIVE_DISPLAY_NAME_COLUMN_INDEX = 5;
+ protected static final int EMAIL_PHOTO_ID_COLUMN_INDEX = 6;
+
+ private CharSequence mUnknownNameText;
+ private int mDisplayNameColumnIndex;
+ private int mAlternativeDisplayNameColumnIndex;
+
+ public EmailAddressListAdapter(Context context) {
+ super(context);
+
+ mUnknownNameText = context.getText(android.R.string.unknownName);
+ }
+
+ @Override
+ public void configureLoader(CursorLoader loader, long directoryId) {
+ final Builder builder;
+ if (isSearchMode()) {
+ builder = Email.CONTENT_FILTER_URI.buildUpon();
+ String query = getQueryString();
+ builder.appendPath(TextUtils.isEmpty(query) ? "" : query);
+ } else {
+ builder = Email.CONTENT_URI.buildUpon();
+ }
+ builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
+ String.valueOf(directoryId));
+ applyDataRestriction(builder);
+ loader.setUri(builder.build());
+ loader.setProjection(EMAILS_PROJECTION);
+
+ if (getSortOrder() == ContactsContract.Preferences.SORT_ORDER_PRIMARY) {
+ loader.setSortOrder(Email.SORT_KEY_PRIMARY);
+ } else {
+ loader.setSortOrder(Email.SORT_KEY_ALTERNATIVE);
+ }
+ }
+
+ protected static Builder buildSectionIndexerUri(Uri uri) {
+ return uri.buildUpon()
+ .appendQueryParameter(ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, "true");
+ }
+
+ @Override
+ public String getContactDisplayName(int position) {
+ return ((Cursor)getItem(position)).getString(mDisplayNameColumnIndex);
+ }
+
+ @Override
+ public void setContactNameDisplayOrder(int displayOrder) {
+ super.setContactNameDisplayOrder(displayOrder);
+ if (getContactNameDisplayOrder() == ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY) {
+ mDisplayNameColumnIndex = EMAIL_PRIMARY_DISPLAY_NAME_COLUMN_INDEX;
+ mAlternativeDisplayNameColumnIndex = EMAIL_ALTERNATIVE_DISPLAY_NAME_COLUMN_INDEX;
+ } else {
+ mDisplayNameColumnIndex = EMAIL_ALTERNATIVE_DISPLAY_NAME_COLUMN_INDEX;
+ mAlternativeDisplayNameColumnIndex = EMAIL_PRIMARY_DISPLAY_NAME_COLUMN_INDEX;
+ }
+ }
+
+ /**
+ * Builds a {@link Data#CONTENT_URI} for the current cursor
+ * position.
+ */
+ public Uri getDataUri(int position) {
+ long id = ((Cursor)getItem(position)).getLong(EMAIL_ID_COLUMN_INDEX);
+ return ContentUris.withAppendedId(Data.CONTENT_URI, id);
+ }
+
+ @Override
+ protected View newView(Context context, int partition, Cursor cursor, int position,
+ ViewGroup parent) {
+ final ContactListItemView view = new ContactListItemView(context, null);
+ view.setUnknownNameText(mUnknownNameText);
+ view.setTextWithHighlightingFactory(getTextWithHighlightingFactory());
+ view.setQuickContactEnabled(isQuickContactEnabled());
+ return view;
+ }
+
+ @Override
+ protected void bindView(View itemView, int partition, Cursor cursor, int position) {
+ ContactListItemView view = (ContactListItemView)itemView;
+ bindSectionHeaderAndDivider(view, position);
+ bindName(view, cursor);
+ bindPhoto(view, cursor);
+ bindEmailAddress(view, cursor);
+ }
+
+ protected void bindEmailAddress(ContactListItemView view, Cursor cursor) {
+ CharSequence label = null;
+ if (!cursor.isNull(EMAIL_TYPE_COLUMN_INDEX)) {
+ final int type = cursor.getInt(EMAIL_TYPE_COLUMN_INDEX);
+ final String customLabel = cursor.getString(EMAIL_LABEL_COLUMN_INDEX);
+
+ // TODO cache
+ label = Email.getTypeLabel(getContext().getResources(), type, customLabel);
+ }
+ view.setLabel(label);
+ view.showData(cursor, EMAIL_ADDRESS_COLUMN_INDEX);
+ }
+
+ protected void bindSectionHeaderAndDivider(final ContactListItemView view, int position) {
+ final int section = getSectionForPosition(position);
+ if (getPositionForSection(section) == position) {
+ String title = (String)getSections()[section];
+ view.setSectionHeader(title);
+ } else {
+ view.setDividerVisible(false);
+ view.setSectionHeader(null);
+ }
+
+ // move the divider for the last item in a section
+ if (getPositionForSection(section + 1) - 1 == position) {
+ view.setDividerVisible(false);
+ } else {
+ view.setDividerVisible(true);
+ }
+ }
+
+ protected void bindName(final ContactListItemView view, Cursor cursor) {
+ view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
+ isNameHighlightingEnabled(), getContactNameDisplayOrder());
+// view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
+ }
+
+ protected void bindPhoto(final ContactListItemView view, Cursor cursor) {
+ long photoId = 0;
+ if (!cursor.isNull(EMAIL_PHOTO_ID_COLUMN_INDEX)) {
+ photoId = cursor.getLong(EMAIL_PHOTO_ID_COLUMN_INDEX);
+ }
+
+ getPhotoLoader().loadPhoto(view.getPhotoView(), photoId);
+ }
+//
+// protected void bindSearchSnippet(final ContactListItemView view, Cursor cursor) {
+// view.showSnippet(cursor, SUMMARY_SNIPPET_MIMETYPE_COLUMN_INDEX,
+// SUMMARY_SNIPPET_DATA1_COLUMN_INDEX, SUMMARY_SNIPPET_DATA4_COLUMN_INDEX);
+// }
+
+}
diff --git a/src/com/android/contacts/list/EmailAddressPickerFragment.java b/src/com/android/contacts/list/EmailAddressPickerFragment.java
new file mode 100644
index 0000000..168e135
--- /dev/null
+++ b/src/com/android/contacts/list/EmailAddressPickerFragment.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import com.android.contacts.R;
+
+import android.net.Uri;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Fragment containing an email list for picking.
+ */
+public class EmailAddressPickerFragment extends ContactEntryListFragment<ContactEntryListAdapter> {
+ private OnEmailAddressPickerActionListener mListener;
+
+ public EmailAddressPickerFragment() {
+ setQuickContactEnabled(false);
+ setPhotoLoaderEnabled(true);
+ setSectionHeaderDisplayEnabled(true);
+ setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_DATA_SHORTCUT);
+ }
+
+ public void setOnEmailAddressPickerActionListener(OnEmailAddressPickerActionListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ protected void onItemClick(int position, long id) {
+ EmailAddressListAdapter adapter = (EmailAddressListAdapter)getAdapter();
+ pickEmailAddress(adapter.getDataUri(position));
+ }
+
+ @Override
+ protected ContactEntryListAdapter createListAdapter() {
+ EmailAddressListAdapter adapter = new EmailAddressListAdapter(getActivity());
+ adapter.setSectionHeaderDisplayEnabled(true);
+ adapter.setDisplayPhotos(true);
+ return adapter;
+ }
+
+ @Override
+ protected View inflateView(LayoutInflater inflater, ViewGroup container) {
+ return inflater.inflate(R.layout.contacts_list_content, null);
+ }
+
+ private void pickEmailAddress(Uri uri) {
+ mListener.onPickEmailAddressAction(uri);
+ }
+}
diff --git a/src/com/android/contacts/list/LegacyContactListAdapter.java b/src/com/android/contacts/list/LegacyContactListAdapter.java
index 6747d1f..ffc8fc3 100644
--- a/src/com/android/contacts/list/LegacyContactListAdapter.java
+++ b/src/com/android/contacts/list/LegacyContactListAdapter.java
@@ -85,7 +85,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, PERSON_DISPLAY_NAME_COLUMN_INDEX, false, 0);
+ view.showDisplayName(cursor, PERSON_DISPLAY_NAME_COLUMN_INDEX, 0, false,
+ getContactNameDisplayOrder());
view.showPhoneticName(cursor, PERSON_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/LegacyPhoneNumberListAdapter.java b/src/com/android/contacts/list/LegacyPhoneNumberListAdapter.java
index 47747fb..547650d 100644
--- a/src/com/android/contacts/list/LegacyPhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/LegacyPhoneNumberListAdapter.java
@@ -89,7 +89,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, PHONE_DISPLAY_NAME_COLUMN_INDEX, false, 0);
+ view.showDisplayName(cursor, PHONE_DISPLAY_NAME_COLUMN_INDEX, 0, false,
+ getContactNameDisplayOrder());
view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/LegacyPostalAddressListAdapter.java b/src/com/android/contacts/list/LegacyPostalAddressListAdapter.java
index 3796c62..48b3f0c 100644
--- a/src/com/android/contacts/list/LegacyPostalAddressListAdapter.java
+++ b/src/com/android/contacts/list/LegacyPostalAddressListAdapter.java
@@ -90,7 +90,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, POSTAL_DISPLAY_NAME_COLUMN_INDEX, false, 0);
+ view.showDisplayName(cursor, POSTAL_DISPLAY_NAME_COLUMN_INDEX, 0, false,
+ getContactNameDisplayOrder());
view.showPhoneticName(cursor, POSTAL_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/OnEmailAddressPickerActionListener.java b/src/com/android/contacts/list/OnEmailAddressPickerActionListener.java
new file mode 100644
index 0000000..e785323
--- /dev/null
+++ b/src/com/android/contacts/list/OnEmailAddressPickerActionListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.list;
+
+import android.net.Uri;
+
+/**
+ * Action callbacks that can be sent by a email address picker.
+ */
+public interface OnEmailAddressPickerActionListener {
+
+ /**
+ * Returns the selected phone number to the requester.
+ */
+ void onPickEmailAddressAction(Uri dataUri);
+}
diff --git a/src/com/android/contacts/list/PhoneNumberListAdapter.java b/src/com/android/contacts/list/PhoneNumberListAdapter.java
index 48a6042..9356bb6 100644
--- a/src/com/android/contacts/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/list/PhoneNumberListAdapter.java
@@ -185,8 +185,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, mDisplayNameColumnIndex, isNameHighlightingEnabled(),
- mAlternativeDisplayNameColumnIndex);
+ view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
+ isNameHighlightingEnabled(), getContactNameDisplayOrder());
view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/PostalAddressListAdapter.java b/src/com/android/contacts/list/PostalAddressListAdapter.java
index e622ec6..86d465a 100644
--- a/src/com/android/contacts/list/PostalAddressListAdapter.java
+++ b/src/com/android/contacts/list/PostalAddressListAdapter.java
@@ -131,7 +131,7 @@
final String customLabel = cursor.getString(POSTAL_LABEL_COLUMN_INDEX);
// TODO cache
- label = StructuredPostal.getTypeLabel(getContext().getResources(), type, label);
+ label = StructuredPostal.getTypeLabel(getContext().getResources(), type, customLabel);
}
view.setLabel(label);
view.showData(cursor, POSTAL_ADDRESS_COLUMN_INDEX);
@@ -156,8 +156,8 @@
}
protected void bindName(final ContactListItemView view, Cursor cursor) {
- view.showDisplayName(cursor, mDisplayNameColumnIndex, isNameHighlightingEnabled(),
- mAlternativeDisplayNameColumnIndex);
+ view.showDisplayName(cursor, mDisplayNameColumnIndex, mAlternativeDisplayNameColumnIndex,
+ isNameHighlightingEnabled(), getContactNameDisplayOrder());
// view.showPhoneticName(cursor, PHONE_PHONETIC_NAME_COLUMN_INDEX);
}
diff --git a/src/com/android/contacts/list/PostalAddressPickerFragment.java b/src/com/android/contacts/list/PostalAddressPickerFragment.java
index f14b718..5f7ca56 100644
--- a/src/com/android/contacts/list/PostalAddressPickerFragment.java
+++ b/src/com/android/contacts/list/PostalAddressPickerFragment.java
@@ -73,7 +73,7 @@
return inflater.inflate(R.layout.contacts_list_content, null);
}
- public void pickPostalAddress(Uri uri) {
+ private void pickPostalAddress(Uri uri) {
mListener.onPickPostalAddressAction(uri);
}
}
diff --git a/src/com/android/contacts/list/StrequentContactListFragment.java b/src/com/android/contacts/list/StrequentContactListFragment.java
index b88a60d..393e698 100644
--- a/src/com/android/contacts/list/StrequentContactListFragment.java
+++ b/src/com/android/contacts/list/StrequentContactListFragment.java
@@ -25,8 +25,6 @@
/**
* Fragment containing a list of starred contacts followed by a list of frequently contacted.
*/
-
-// TODO: This class is currently unused. Bring it back as a mode of ContactBrowserListFragment
public class StrequentContactListFragment extends ContactBrowseListFragment
implements OnClickListener {
diff --git a/src/com/android/contacts/model/AccountType.java b/src/com/android/contacts/model/AccountType.java
index aef5c06..462f7ad 100644
--- a/src/com/android/contacts/model/AccountType.java
+++ b/src/com/android/contacts/model/AccountType.java
@@ -30,15 +30,12 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
-import android.view.View;
import android.widget.EditText;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.List;
/**
* Internal structure that represents constraints and styles for a specific data
@@ -160,87 +157,6 @@
}
/**
- * Description of a specific data type, usually marked by a unique
- * {@link Data#MIMETYPE}. Includes details about how to view and edit
- * {@link Data} rows of this kind, including the possible {@link EditType}
- * labels and editable {@link EditField}.
- */
- public static class DataKind {
-
- public static final String PSEUDO_MIME_TYPE_DISPLAY_NAME = "#displayName";
- public static final String PSEUDO_MIME_TYPE_PHONETIC_NAME = "#phoneticName";
- public static final String PSEUDO_COLUMN_PHONETIC_NAME = "#phoneticName";
-
- public String resPackageName;
- public String mimeType;
- public int titleRes;
- public int iconRes;
- public int iconAltRes;
- public int weight;
- public boolean editable;
-
- /**
- * If this is true (default), the user can add and remove values.
- * If false, the editor will always show a single field (which might be empty).
- */
- public boolean isList;
-
- public StringInflater actionHeader;
- public StringInflater actionAltHeader;
- public StringInflater actionBody;
-
- public boolean actionBodySocial = false;
-
- public String typeColumn;
-
- /**
- * Maximum number of values allowed in the list. -1 represents infinity.
- * If {@link DataKind#isList} is false, this value is ignored.
- */
- public int typeOverallMax;
-
- public List<EditType> typeList;
- public List<EditField> fieldList;
-
- public ContentValues defaultValues;
-
- public Class<? extends View> editorClass;
-
- /**
- * If this is a date field, this specifies the format of the date when saving. The
- * date includes year, month and day. If this is not a date field or the date field is not
- * editable, this value should be ignored.
- */
- public SimpleDateFormat dateFormatWithoutYear;
-
- /**
- * If this is a date field, this specifies the format of the date when saving. The
- * date includes month and day. If this is not a date field, the field is not editable or
- * dates without year are not supported, this value should be ignored.
- */
- public SimpleDateFormat dateFormatWithYear;
-
- public DataKind() {
- }
-
- public DataKind(String mimeType, int titleRes, int iconRes, int weight, boolean editable) {
- this(mimeType, titleRes, iconRes, weight, editable, null);
- }
-
- public DataKind(String mimeType, int titleRes, int iconRes, int weight, boolean editable,
- Class<? extends View> editorClass) {
- this.mimeType = mimeType;
- this.titleRes = titleRes;
- this.iconRes = iconRes;
- this.weight = weight;
- this.editable = editable;
- this.isList = true;
- this.typeOverallMax = -1;
- this.editorClass = editorClass;
- }
- }
-
- /**
* Description of a specific "type" or "label" of a {@link DataKind} row,
* such as {@link Phone#TYPE_WORK}. Includes constraints on total number of
* rows a {@link Contacts} may have of this type, and details on how
@@ -250,6 +166,10 @@
public int rawValue;
public int labelRes;
public boolean secondary;
+ /**
+ * The number of entries allowed for the type. -1 if not specified.
+ * @see DataKind#typeOverallMax
+ */
public int specificMax;
public String customColumn;
@@ -329,6 +249,7 @@
public boolean optional;
public boolean shortForm;
public boolean longForm;
+ public boolean isFullName;
public EditField(String column, int titleRes) {
this.column = column;
@@ -359,6 +280,11 @@
this.minLines = minLines;
return this;
}
+
+ public EditField setIsFullName(boolean isFullName) {
+ this.isFullName = isFullName;
+ return this;
+ }
}
/**
diff --git a/src/com/android/contacts/model/AccountTypeManager.java b/src/com/android/contacts/model/AccountTypeManager.java
index 06bb9bd..58195a1 100644
--- a/src/com/android/contacts/model/AccountTypeManager.java
+++ b/src/com/android/contacts/model/AccountTypeManager.java
@@ -16,7 +16,6 @@
package com.android.contacts.model;
-import com.android.contacts.model.AccountType.DataKind;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index d4a7496..fd8f914 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -99,7 +99,8 @@
protected DataKind addDataKindStructuredName(Context context) {
DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
- R.string.nameLabelsGroup, -1, -1, true));
+ R.string.nameLabelsGroup, -1, -1, true, R.layout.structured_name_editor_view,
+ android.R.style.TextAppearance_Large, -1));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -128,13 +129,14 @@
protected DataKind addDataKindDisplayName(Context context) {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
- R.string.nameLabelsGroup, -1, -1, true));
+ R.string.nameLabelsGroup, -1, -1, true, R.layout.text_fields_editor_view,
+ android.R.style.TextAppearance_Large, -1));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME,
- R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true));
+ R.string.full_name, FLAGS_PERSON_NAME).setShortForm(true).setIsFullName(true));
boolean displayOrderPrimary =
context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
@@ -168,7 +170,8 @@
protected DataKind addDataKindPhoneticName(Context context) {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
- R.string.name_phonetic, -1, -1, true));
+ R.string.name_phonetic, -1, -1, true, R.layout.phonetic_name_editor_view,
+ android.R.style.TextAppearance_Medium, -1));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -187,8 +190,8 @@
protected DataKind addDataKindNickname(Context context) {
DataKind kind = addKind(new DataKind(Nickname.CONTENT_ITEM_TYPE,
- R.string.nicknameLabelsGroup, -1, 115, true));
-
+ R.string.nicknameLabelsGroup, -1, 115, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium, -1));
kind.isList = false;
kind.actionHeader = new SimpleInflater(R.string.nicknameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -204,7 +207,9 @@
protected DataKind addDataKindPhone(Context context) {
DataKind kind = addKind(new DataKind(Phone.CONTENT_ITEM_TYPE, R.string.phoneLabelsGroup,
- android.R.drawable.sym_action_call, 10, true));
+ android.R.drawable.sym_action_call, 10, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Large,
+ R.string.add_phone));
kind.iconAltRes = R.drawable.sym_action_sms;
kind.actionHeader = new PhoneActionInflater();
kind.actionAltHeader = new PhoneActionAltInflater();
@@ -243,7 +248,9 @@
protected DataKind addDataKindEmail(Context context) {
DataKind kind = addKind(new DataKind(Email.CONTENT_ITEM_TYPE, R.string.emailLabelsGroup,
- R.drawable.sym_action_email_holo_light, 15, true));
+ R.drawable.sym_action_email_holo_light, 15, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_email));
kind.actionHeader = new EmailActionInflater();
kind.actionBody = new SimpleInflater(Email.DATA);
kind.typeColumn = Email.TYPE;
@@ -264,7 +271,8 @@
protected DataKind addDataKindStructuredPostal(Context context) {
DataKind kind = addKind(new DataKind(StructuredPostal.CONTENT_ITEM_TYPE,
R.string.postalLabelsGroup, R.drawable.sym_action_show_map_holo_light, 25,
- true));
+ true, R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_address));
kind.actionHeader = new PostalActionInflater();
kind.actionBody = new SimpleInflater(StructuredPostal.FORMATTED_ADDRESS);
kind.typeColumn = StructuredPostal.TYPE;
@@ -285,7 +293,9 @@
protected DataKind addDataKindIm(Context context) {
DataKind kind = addKind(new DataKind(Im.CONTENT_ITEM_TYPE, R.string.imLabelsGroup,
- R.drawable.sym_action_talk_holo_light, 20, true));
+ R.drawable.sym_action_talk_holo_light, 20, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_im));
kind.actionHeader = new ImActionInflater();
kind.actionBody = new SimpleInflater(Im.DATA);
@@ -316,7 +326,8 @@
protected DataKind addDataKindOrganization(Context context) {
DataKind kind = addKind(new DataKind(Organization.CONTENT_ITEM_TYPE,
- R.string.organizationLabelsGroup, -1, 5, true));
+ R.string.organizationLabelsGroup, -1, 5, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium, -1));
kind.actionHeader = new SimpleInflater(Organization.COMPANY);
kind.actionBody = new SimpleInflater(Organization.TITLE);
kind.isList = false;
@@ -331,7 +342,8 @@
}
protected DataKind addDataKindPhoto(Context context) {
- DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true));
+ DataKind kind = addKind(new DataKind(Photo.CONTENT_ITEM_TYPE, -1, -1, -1, true, -1,
+ android.R.style.TextAppearance_Medium, -1));
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(Photo.PHOTO, -1, -1));
return kind;
@@ -339,7 +351,9 @@
protected DataKind addDataKindNote(Context context) {
DataKind kind = addKind(new DataKind(Note.CONTENT_ITEM_TYPE,
- R.string.label_notes, -1, 110, true));
+ R.string.label_notes, -1, 110, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_note));
kind.isList = false;
kind.actionHeader = new SimpleInflater(R.string.label_notes);
kind.actionBody = new SimpleInflater(Note.NOTE);
@@ -352,7 +366,8 @@
protected DataKind addDataKindWebsite(Context context) {
DataKind kind = addKind(new DataKind(Website.CONTENT_ITEM_TYPE,
R.string.websiteLabelsGroup, R.drawable.sym_action_goto_website_holo_light, 120,
- true));
+ true, R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_website));
kind.actionHeader = new SimpleInflater(R.string.websiteLabelsGroup);
kind.actionBody = new SimpleInflater(Website.URL);
kind.defaultValues = new ContentValues();
@@ -374,7 +389,9 @@
// the android:icon attribute of the SIP-related
// intent-filters in the Phone app's manifest.
DataKind kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
- R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
+ R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ -1));
kind.isList = false;
kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
@@ -389,7 +406,8 @@
protected DataKind addDataKindGroupMembership(Context context) {
DataKind kind = getKindForMimetype(GroupMembership.CONTENT_ITEM_TYPE);
kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
- R.string.groupsLabel, android.R.drawable.sym_contact_card, 999, true));
+ R.string.groupsLabel, android.R.drawable.sym_contact_card, 999, true, -1,
+ android.R.style.TextAppearance_Medium, -1));
kind.isList = false;
kind.fieldList = Lists.newArrayList();
diff --git a/src/com/android/contacts/model/DataKind.java b/src/com/android/contacts/model/DataKind.java
new file mode 100644
index 0000000..52769c3
--- /dev/null
+++ b/src/com/android/contacts/model/DataKind.java
@@ -0,0 +1,106 @@
+package com.android.contacts.model;
+
+import com.android.contacts.R;
+import com.android.contacts.model.AccountType.EditField;
+import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.AccountType.StringInflater;
+
+import android.content.ContentValues;
+import android.provider.ContactsContract.Data;
+
+import java.text.SimpleDateFormat;
+import java.util.List;
+
+/**
+ * Description of a specific data type, usually marked by a unique
+ * {@link Data#MIMETYPE}. Includes details about how to view and edit
+ * {@link Data} rows of this kind, including the possible {@link EditType}
+ * labels and editable {@link EditField}.
+ */
+public class DataKind {
+
+ public static final String PSEUDO_MIME_TYPE_DISPLAY_NAME = "#displayName";
+ public static final String PSEUDO_MIME_TYPE_PHONETIC_NAME = "#phoneticName";
+ public static final String PSEUDO_COLUMN_PHONETIC_NAME = "#phoneticName";
+
+ public String resPackageName;
+ public String mimeType;
+ public int titleRes;
+ public int iconRes;
+ public int iconAltRes;
+ public int weight;
+ public boolean editable;
+
+ /**
+ * If this is true (default), the user can add and remove values.
+ * If false, the editor will always show a single field (which might be empty).
+ */
+ public boolean isList;
+
+ public StringInflater actionHeader;
+ public StringInflater actionAltHeader;
+ public StringInflater actionBody;
+
+ public boolean actionBodySocial = false;
+
+ public String typeColumn;
+
+ /**
+ * Maximum number of values allowed in the list. -1 represents infinity.
+ * If {@link DataKind#isList} is false, this value is ignored.
+ */
+ public int typeOverallMax;
+
+ public List<EditType> typeList;
+ public List<EditField> fieldList;
+
+ public ContentValues defaultValues;
+
+ /** Layout resource id for an editor view to edit this {@link DataKind}. */
+ public final int editorLayoutResourceId;
+
+ /** Text appearance resource id for the value of a field in this {@link DataKind}. */
+ public final int textAppearanceResourceId;
+
+ /**
+ * String resource id for the "add field" footer. This is equal to -1 if it
+ * is not applicable to add a new field to this class (i.e. for a structured
+ * name because a user should only have one structured name).
+ */
+ public final int addNewFieldTextResourceId;
+
+ /**
+ * If this is a date field, this specifies the format of the date when saving. The
+ * date includes year, month and day. If this is not a date field or the date field is not
+ * editable, this value should be ignored.
+ */
+ public SimpleDateFormat dateFormatWithoutYear;
+
+ /**
+ * If this is a date field, this specifies the format of the date when saving. The
+ * date includes month and day. If this is not a date field, the field is not editable or
+ * dates without year are not supported, this value should be ignored.
+ */
+ public SimpleDateFormat dateFormatWithYear;
+
+ public DataKind() {
+ editorLayoutResourceId = R.layout.text_fields_editor_view;
+ textAppearanceResourceId = android.R.style.TextAppearance_Medium;
+ addNewFieldTextResourceId = -1;
+ }
+
+ public DataKind(String mimeType, int titleRes, int iconRes, int weight, boolean editable,
+ int editorLayoutResourceId, int textAppearanceResourceId,
+ int addNewFieldTextResourceId) {
+ this.mimeType = mimeType;
+ this.titleRes = titleRes;
+ this.iconRes = iconRes;
+ this.weight = weight;
+ this.editable = editable;
+ this.isList = true;
+ this.typeOverallMax = -1;
+ this.editorLayoutResourceId = editorLayoutResourceId;
+ this.textAppearanceResourceId = textAppearanceResourceId;
+ this.addNewFieldTextResourceId = addNewFieldTextResourceId;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/EntityDelta.java
index c5d0d9e..fe084f4 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/EntityDelta.java
@@ -330,7 +330,7 @@
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("\n(");
- builder.append(mValues.toString());
+ builder.append(mValues != null ? mValues.toString() : "null");
builder.append(") = {");
for (ArrayList<ValuesDelta> mimeEntries : mEntries.values()) {
for (ValuesDelta child : mimeEntries) {
diff --git a/src/com/android/contacts/model/EntityModifier.java b/src/com/android/contacts/model/EntityModifier.java
index 1e014ef..9d527df 100644
--- a/src/com/android/contacts/model/EntityModifier.java
+++ b/src/com/android/contacts/model/EntityModifier.java
@@ -17,11 +17,14 @@
package com.android.contacts.model;
import com.android.contacts.ContactsUtils;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.editor.EventFieldEditorView;
+import com.android.contacts.util.NameConverter;
+import com.android.contacts.editor.PhoneticNameEditorView;
import com.android.contacts.model.AccountType.EditField;
import com.android.contacts.model.AccountType.EditType;
+import com.android.contacts.model.AccountType.EventEditType;
import com.android.contacts.model.EntityDelta.ValuesDelta;
-import com.google.android.collect.Lists;
+import com.android.contacts.util.DateUtils;
import android.content.ContentValues;
import android.content.Context;
@@ -31,14 +34,19 @@
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.Relation;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Intents;
import android.provider.ContactsContract.Intents.Insert;
@@ -47,9 +55,18 @@
import android.util.Log;
import android.util.SparseIntArray;
+import java.text.ParsePosition;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
/**
* Helper methods for modifying an {@link EntityDelta}, such as inserting
@@ -137,7 +154,7 @@
*/
private static ArrayList<EditType> getValidTypes(EntityDelta state, DataKind kind,
EditType forceInclude, boolean includeSecondary, SparseIntArray typeCount) {
- final ArrayList<EditType> validTypes = Lists.newArrayList();
+ final ArrayList<EditType> validTypes = new ArrayList<EditType>();
// Bail early if no types provided
if (!hasEditTypes(kind)) return validTypes;
@@ -878,4 +895,503 @@
return child;
}
+
+ /**
+ * Generic mime types with type support (e.g. TYPE_HOME).
+ * Here, "type support" means if the data kind has CommonColumns#TYPE or not. Data kinds which
+ * have their own migrate methods aren't listed here.
+ */
+ private static final Set<String> sGenericMimeTypesWithTypeSupport = new HashSet<String>(
+ Arrays.asList(Phone.CONTENT_ITEM_TYPE,
+ Email.CONTENT_ITEM_TYPE,
+ Im.CONTENT_ITEM_TYPE,
+ Nickname.CONTENT_ITEM_TYPE,
+ Website.CONTENT_ITEM_TYPE,
+ Relation.CONTENT_ITEM_TYPE,
+ SipAddress.CONTENT_ITEM_TYPE));
+ private static final Set<String> sGenericMimeTypesWithoutTypeSupport = new HashSet<String>(
+ Arrays.asList(Organization.CONTENT_ITEM_TYPE,
+ Note.CONTENT_ITEM_TYPE,
+ Photo.CONTENT_ITEM_TYPE,
+ GroupMembership.CONTENT_ITEM_TYPE));
+ // CommonColumns.TYPE cannot be accessed as it is protected interface, so use
+ // Phone.TYPE instead.
+ private static final String COLUMN_FOR_TYPE = Phone.TYPE;
+ private static final String COLUMN_FOR_LABEL = Phone.LABEL;
+ private static final int TYPE_CUSTOM = Phone.TYPE_CUSTOM;
+
+ /**
+ * Migrates old EntityDelta to newly created one with a new restriction supplied from
+ * newAccountType.
+ *
+ * This is only for account switch during account creation (which must be insert operation).
+ */
+ public static void migrateStateForNewContact(Context context,
+ EntityDelta oldState, EntityDelta newState,
+ AccountType oldAccountType, AccountType newAccountType) {
+ if (newAccountType == oldAccountType) {
+ // Just copying all data in oldState isn't enough, but we can still rely on a lot of
+ // shortcuts.
+ for (DataKind kind : newAccountType.getSortedDataKinds()) {
+ final String mimeType = kind.mimeType;
+ // The fields with short/long form capability must be treated properly.
+ if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ migrateStructuredName(context, oldState, newState, kind);
+ } else {
+ List<ValuesDelta> entryList = oldState.getMimeEntries(mimeType);
+ if (entryList != null && !entryList.isEmpty()) {
+ for (ValuesDelta entry : entryList) {
+ ContentValues values = entry.getAfter();
+ if (values != null) {
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // Migrate data supported by the new account type.
+ // All the other data inside oldState are silently dropped.
+ for (DataKind kind : newAccountType.getSortedDataKinds()) {
+ final String mimeType = kind.mimeType;
+ final int fieldCount = kind.fieldList.size();
+ final Set<String> allowedColumns = new HashSet<String>();
+ if (DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME.equals(mimeType)
+ || DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME.equals(mimeType)) {
+ // Ignore pseude data.
+ continue;
+ } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ migrateStructuredName(context, oldState, newState, kind);
+ } else if (StructuredPostal.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ migratePostal(oldState, newState, kind);
+ } else if (Event.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ migrateEvent(oldState, newState, kind, null /* default Year */);
+ } else if (sGenericMimeTypesWithoutTypeSupport.contains(mimeType)) {
+ migrateGenericWithoutTypeColumn(oldState, newState, kind);
+ } else {
+ migrateGenericWithTypeColumn(oldState, newState, kind);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks {@link DataKind#isList} and {@link DataKind#typeOverallMax}, and restricts
+ * the number of entries (ValuesDelta) inside newState.
+ */
+ private static ArrayList<ValuesDelta> ensureEntryMaxSize(EntityDelta newState, DataKind kind,
+ ArrayList<ValuesDelta> mimeEntries) {
+ if (mimeEntries == null) {
+ return null;
+ }
+
+ int typeOverallMax = kind.typeOverallMax;
+ if (!kind.isList) {
+ typeOverallMax = 1;
+ }
+ if (typeOverallMax >= 0 && (mimeEntries.size() > typeOverallMax)) {
+ ArrayList<ValuesDelta> newMimeEntries = new ArrayList<ValuesDelta>(typeOverallMax);
+ for (int i = 0; i < typeOverallMax; i++) {
+ newMimeEntries.add(mimeEntries.get(i));
+ }
+ mimeEntries = newMimeEntries;
+ }
+ return mimeEntries;
+ }
+
+ /** @hide Public only for testing. */
+ public static void migrateStructuredName(
+ Context context, EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+ final ContentValues values =
+ oldState.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE).getAfter();
+ if (values == null) {
+ return;
+ }
+
+ boolean supportDisplayName = false;
+ boolean supportPhoneticFullName = false;
+ boolean supportPhoneticFamilyName = false;
+ boolean supportPhoneticMiddleName = false;
+ boolean supportPhoneticGivenName = false;
+ for (EditField editField : newDataKind.fieldList) {
+ if (StructuredName.DISPLAY_NAME.equals(editField.column)) {
+ supportDisplayName = true;
+ }
+ if (DataKind.PSEUDO_COLUMN_PHONETIC_NAME.equals(editField.column)) {
+ supportPhoneticFullName = true;
+ }
+ if (StructuredName.PHONETIC_FAMILY_NAME.equals(editField.column)) {
+ supportPhoneticFamilyName = true;
+ }
+ if (StructuredName.PHONETIC_MIDDLE_NAME.equals(editField.column)) {
+ supportPhoneticMiddleName = true;
+ }
+ if (StructuredName.PHONETIC_GIVEN_NAME.equals(editField.column)) {
+ supportPhoneticGivenName = true;
+ }
+ }
+
+ // DISPLAY_NAME <-> PREFIX, GIVEN_NAME, MIDDLE_NAME, FAMILY_NAME, SUFFIX
+ final String displayName = values.getAsString(StructuredName.DISPLAY_NAME);
+ if (!TextUtils.isEmpty(displayName)) {
+ if (!supportDisplayName) {
+ // Old data has a display name, while the new account doesn't allow it.
+ NameConverter.displayNameToStructuredName(context, displayName, values);
+
+ // We don't want to migrate unseen data which may confuse users after the creation.
+ values.remove(StructuredName.DISPLAY_NAME);
+ }
+ } else {
+ if (supportDisplayName) {
+ // Old data does not have display name, while the new account requires it.
+ values.put(StructuredName.DISPLAY_NAME,
+ NameConverter.structuredNameToDisplayName(context, values));
+ for (String field : NameConverter.STRUCTURED_NAME_FIELDS) {
+ values.remove(field);
+ }
+ }
+ }
+
+ // Phonetic (full) name <-> PHONETIC_FAMILY_NAME, PHONETIC_MIDDLE_NAME, PHONETIC_GIVEN_NAME
+ final String phoneticFullName = values.getAsString(DataKind.PSEUDO_COLUMN_PHONETIC_NAME);
+ if (!TextUtils.isEmpty(phoneticFullName)) {
+ if (!supportPhoneticFullName) {
+ // Old data has a phonetic (full) name, while the new account doesn't allow it.
+ final ContentValues tmpValues =
+ PhoneticNameEditorView.parsePhoneticName(phoneticFullName, null);
+ values.remove(DataKind.PSEUDO_COLUMN_PHONETIC_NAME);
+ if (supportPhoneticFamilyName) {
+ values.put(StructuredName.PHONETIC_FAMILY_NAME,
+ tmpValues.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
+ } else {
+ values.remove(StructuredName.PHONETIC_FAMILY_NAME);
+ }
+ if (supportPhoneticMiddleName) {
+ values.put(StructuredName.PHONETIC_MIDDLE_NAME,
+ tmpValues.getAsString(StructuredName.PHONETIC_MIDDLE_NAME));
+ } else {
+ values.remove(StructuredName.PHONETIC_MIDDLE_NAME);
+ }
+ if (supportPhoneticGivenName) {
+ values.put(StructuredName.PHONETIC_GIVEN_NAME,
+ tmpValues.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
+ } else {
+ values.remove(StructuredName.PHONETIC_GIVEN_NAME);
+ }
+ }
+ } else {
+ if (supportPhoneticFullName) {
+ // Old data does not have a phonetic (full) name, while the new account requires it.
+ values.put(DataKind.PSEUDO_COLUMN_PHONETIC_NAME,
+ PhoneticNameEditorView.buildPhoneticName(
+ values.getAsString(StructuredName.PHONETIC_FAMILY_NAME),
+ values.getAsString(StructuredName.PHONETIC_MIDDLE_NAME),
+ values.getAsString(StructuredName.PHONETIC_GIVEN_NAME)));
+ }
+ if (!supportPhoneticFamilyName) {
+ values.remove(StructuredName.PHONETIC_FAMILY_NAME);
+ }
+ if (!supportPhoneticMiddleName) {
+ values.remove(StructuredName.PHONETIC_MIDDLE_NAME);
+ }
+ if (!supportPhoneticGivenName) {
+ values.remove(StructuredName.PHONETIC_GIVEN_NAME);
+ }
+ }
+
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ }
+
+ /** @hide Public only for testing. */
+ public static void migratePostal(EntityDelta oldState, EntityDelta newState,
+ DataKind newDataKind) {
+ final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
+ oldState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
+ if (mimeEntries == null || mimeEntries.isEmpty()) {
+ return;
+ }
+
+ boolean supportFormattedAddress = false;
+ boolean supportStreet = false;
+ final String firstColumn = newDataKind.fieldList.get(0).column;
+ for (EditField editField : newDataKind.fieldList) {
+ if (StructuredPostal.FORMATTED_ADDRESS.equals(editField.column)) {
+ supportFormattedAddress = true;
+ }
+ if (StructuredPostal.STREET.equals(editField.column)) {
+ supportStreet = true;
+ }
+ }
+
+ final Set<Integer> supportedTypes = new HashSet<Integer>();
+ if (newDataKind.typeList != null && !newDataKind.typeList.isEmpty()) {
+ for (EditType editType : newDataKind.typeList) {
+ supportedTypes.add(editType.rawValue);
+ }
+ }
+
+ for (ValuesDelta entry : mimeEntries) {
+ final ContentValues values = entry.getAfter();
+ if (values == null) {
+ continue;
+ }
+ final Integer oldType = values.getAsInteger(StructuredPostal.TYPE);
+ if (!supportedTypes.contains(oldType)) {
+ int defaultType;
+ if (newDataKind.defaultValues != null) {
+ defaultType = newDataKind.defaultValues.getAsInteger(StructuredPostal.TYPE);
+ } else {
+ defaultType = newDataKind.typeList.get(0).rawValue;
+ }
+ values.put(StructuredPostal.TYPE, defaultType);
+ if (oldType != null && oldType == StructuredPostal.TYPE_CUSTOM) {
+ values.remove(StructuredPostal.LABEL);
+ }
+ }
+
+ final String formattedAddress = values.getAsString(StructuredPostal.FORMATTED_ADDRESS);
+ if (!TextUtils.isEmpty(formattedAddress)) {
+ if (!supportFormattedAddress) {
+ // Old data has a formatted address, while the new account doesn't allow it.
+ values.remove(StructuredPostal.FORMATTED_ADDRESS);
+
+ // Unlike StructuredName we don't have logic to split it, so first
+ // try to use street field and. If the new account doesn't have one,
+ // then select first one anyway.
+ if (supportStreet) {
+ values.put(StructuredPostal.STREET, formattedAddress);
+ } else {
+ values.put(firstColumn, formattedAddress);
+ }
+ }
+ } else {
+ if (supportFormattedAddress) {
+ // Old data does not have formatted address, while the new account requires it.
+ // Unlike StructuredName we don't have logic to join multiple address values.
+ // Use poor join heuristics for now.
+ String[] structuredData;
+ final boolean useJapaneseOrder =
+ Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage());
+ if (useJapaneseOrder) {
+ structuredData = new String[] {
+ values.getAsString(StructuredPostal.COUNTRY),
+ values.getAsString(StructuredPostal.POSTCODE),
+ values.getAsString(StructuredPostal.REGION),
+ values.getAsString(StructuredPostal.CITY),
+ values.getAsString(StructuredPostal.NEIGHBORHOOD),
+ values.getAsString(StructuredPostal.STREET),
+ values.getAsString(StructuredPostal.POBOX) };
+ } else {
+ structuredData = new String[] {
+ values.getAsString(StructuredPostal.POBOX),
+ values.getAsString(StructuredPostal.STREET),
+ values.getAsString(StructuredPostal.NEIGHBORHOOD),
+ values.getAsString(StructuredPostal.CITY),
+ values.getAsString(StructuredPostal.REGION),
+ values.getAsString(StructuredPostal.POSTCODE),
+ values.getAsString(StructuredPostal.COUNTRY) };
+ }
+ final StringBuilder builder = new StringBuilder();
+ for (String elem : structuredData) {
+ if (!TextUtils.isEmpty(elem)) {
+ builder.append(elem + "\n");
+ }
+ }
+ values.put(StructuredPostal.FORMATTED_ADDRESS, builder.toString());
+
+ values.remove(StructuredPostal.POBOX);
+ values.remove(StructuredPostal.STREET);
+ values.remove(StructuredPostal.NEIGHBORHOOD);
+ values.remove(StructuredPostal.CITY);
+ values.remove(StructuredPostal.REGION);
+ values.remove(StructuredPostal.POSTCODE);
+ values.remove(StructuredPostal.COUNTRY);
+ }
+ }
+
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ }
+ }
+
+ /** @hide Public only for testing. */
+ public static void migrateEvent(EntityDelta oldState, EntityDelta newState,
+ DataKind newDataKind, Integer defaultYear) {
+ final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
+ oldState.getMimeEntries(Event.CONTENT_ITEM_TYPE));
+ if (mimeEntries == null || mimeEntries.isEmpty()) {
+ return;
+ }
+
+ final Map<Integer, EventEditType> allowedTypes = new HashMap<Integer, EventEditType>();
+ for (EditType editType : newDataKind.typeList) {
+ allowedTypes.put(editType.rawValue, (EventEditType) editType);
+ }
+ for (ValuesDelta entry : mimeEntries) {
+ final ContentValues values = entry.getAfter();
+ if (values == null) {
+ continue;
+ }
+ final String dateString = values.getAsString(Event.START_DATE);
+ final Integer type = values.getAsInteger(Event.TYPE);
+ if (type != null && allowedTypes.containsKey(type) && !TextUtils.isEmpty(dateString)) {
+ EventEditType suitableType = allowedTypes.get(type);
+
+ final ParsePosition position = new ParsePosition(0);
+ boolean yearOptional = false;
+ Date date = DateUtils.DATE_AND_TIME_FORMAT.parse(dateString, position);
+ if (date == null) {
+ yearOptional = true;
+ date = DateUtils.NO_YEAR_DATE_FORMAT.parse(dateString, position);
+ }
+ if (date != null) {
+ if (yearOptional && !suitableType.isYearOptional()) {
+ // The new EditType doesn't allow optional year. Supply default.
+ final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE,
+ Locale.US);
+ if (defaultYear == null) {
+ defaultYear = calendar.get(Calendar.YEAR);
+ }
+ calendar.setTime(date);
+ final int month = calendar.get(Calendar.MONTH);
+ final int day = calendar.get(Calendar.DAY_OF_MONTH);
+ // Exchange requires 8:00 for birthdays
+ calendar.set(defaultYear, month, day,
+ EventFieldEditorView.getDefaultHourForBirthday(), 0, 0);
+ values.put(Event.START_DATE,
+ DateUtils.FULL_DATE_FORMAT.format(calendar.getTime()));
+ }
+ }
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ } else {
+ // Just drop it.
+ }
+ }
+ }
+
+ /** @hide Public only for testing. */
+ public static void migrateGenericWithoutTypeColumn(
+ EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+ final ArrayList<ValuesDelta> mimeEntries = ensureEntryMaxSize(newState, newDataKind,
+ oldState.getMimeEntries(newDataKind.mimeType));
+ if (mimeEntries == null || mimeEntries.isEmpty()) {
+ return;
+ }
+
+ for (ValuesDelta entry : mimeEntries) {
+ ContentValues values = entry.getAfter();
+ if (values != null) {
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ }
+ }
+ }
+
+ /** @hide Public only for testing. */
+ public static void migrateGenericWithTypeColumn(
+ EntityDelta oldState, EntityDelta newState, DataKind newDataKind) {
+ if (!sGenericMimeTypesWithTypeSupport.contains(newDataKind.mimeType)) {
+ throw new RuntimeException("not supported: " + newDataKind.mimeType);
+ }
+
+ final ArrayList<ValuesDelta> mimeEntries = oldState.getMimeEntries(newDataKind.mimeType);
+ if (mimeEntries == null || mimeEntries.isEmpty()) {
+ return;
+ }
+
+ // Note that type specified with the old account may be invalid with the new account, while
+ // we want to preserve its data as much as possible. e.g. if a user typed a phone number
+ // with a type which is valid with an old account but not with a new account, the user
+ // probably wants to have the number with default type, rather than seeing complete data
+ // loss.
+ //
+ // Specifically, this method works as follows:
+ // 1. detect defaultType
+ // 2. prepare constants & variables for iteration
+ // 3. iterate over mimeEntries:
+ // 3.1 stop iteration if total number of mimeEntries reached typeOverallMax specified in
+ // DataKind
+ // 3.2 replace unallowed types with defaultType
+ // 3.3 check if the number of entries is below specificMax specified in AccountType
+
+ // Here, defaultType can be supplied in two ways
+ // - via kind.defaultValues
+ // - via kind.typeList.get(0).rawValue
+ Integer defaultType = null;
+ if (newDataKind.defaultValues != null) {
+ defaultType = newDataKind.defaultValues.getAsInteger(COLUMN_FOR_TYPE);
+ }
+ final Set<Integer> allowedTypes = new HashSet<Integer>();
+ // key: type, value: the number of entries allowed for the type (specificMax)
+ final Map<Integer, Integer> typeSpecificMaxMap = new HashMap<Integer, Integer>();
+ if (defaultType != null) {
+ allowedTypes.add(defaultType);
+ typeSpecificMaxMap.put(defaultType, -1);
+ }
+ // Note: typeList may be used in different purposes when defaultValues are specified.
+ // Especially in IM, typeList contains available protocols (e.g. PROTOCOL_GOOGLE_TALK)
+ // instead of "types" which we want to treate here (e.g. TYPE_HOME). So we don't add
+ // anything other than defaultType into allowedTypes and typeSpecificMapMax.
+ if (!Im.CONTENT_ITEM_TYPE.equals(newDataKind.mimeType) &&
+ newDataKind.typeList != null && !newDataKind.typeList.isEmpty()) {
+ for (EditType editType : newDataKind.typeList) {
+ allowedTypes.add(editType.rawValue);
+ typeSpecificMaxMap.put(editType.rawValue, editType.specificMax);
+ }
+ if (defaultType == null) {
+ defaultType = newDataKind.typeList.get(0).rawValue;
+ }
+ }
+
+ if (defaultType == null) {
+ Log.w(TAG, "Default type isn't available for mimetype " + newDataKind.mimeType);
+ }
+
+ final int typeOverallMax = newDataKind.isList ? newDataKind.typeOverallMax : 1;
+
+ // key: type, value: the number of current entries.
+ final Map<Integer, Integer> currentEntryCount = new HashMap<Integer, Integer>();
+ int totalCount = 0;
+
+ for (ValuesDelta entry : mimeEntries) {
+ if (typeOverallMax != -1 && totalCount >= typeOverallMax) {
+ break;
+ }
+
+ final ContentValues values = entry.getAfter();
+ if (values == null) {
+ continue;
+ }
+
+ final Integer oldType = entry.getAsInteger(COLUMN_FOR_TYPE);
+ final Integer typeForNewAccount;
+ if (!allowedTypes.contains(oldType)) {
+ // The new account doesn't support the type.
+ if (defaultType != null) {
+ typeForNewAccount = defaultType.intValue();
+ values.put(COLUMN_FOR_TYPE, defaultType.intValue());
+ if (oldType != null && oldType == TYPE_CUSTOM) {
+ values.remove(COLUMN_FOR_LABEL);
+ }
+ } else {
+ typeForNewAccount = null;
+ values.remove(COLUMN_FOR_TYPE);
+ }
+ } else {
+ typeForNewAccount = oldType;
+ }
+ if (typeForNewAccount != null) {
+ final int specificMax = (typeSpecificMaxMap.containsKey(typeForNewAccount) ?
+ typeSpecificMaxMap.get(typeForNewAccount) : 0);
+ if (specificMax >= 0) {
+ final int currentCount = (currentEntryCount.get(typeForNewAccount) != null ?
+ currentEntryCount.get(typeForNewAccount) : 0);
+ if (currentCount >= specificMax) {
+ continue;
+ }
+ currentEntryCount.put(typeForNewAccount, currentCount + 1);
+ }
+ }
+ newState.addEntry(ValuesDelta.fromAfter(values));
+ totalCount++;
+ }
+ }
}
diff --git a/src/com/android/contacts/model/ExchangeAccountType.java b/src/com/android/contacts/model/ExchangeAccountType.java
index 2b1a520..22a2ba2 100644
--- a/src/com/android/contacts/model/ExchangeAccountType.java
+++ b/src/com/android/contacts/model/ExchangeAccountType.java
@@ -17,7 +17,6 @@
package com.android.contacts.model;
import com.android.contacts.R;
-import com.android.contacts.editor.EventFieldEditorView;
import com.android.contacts.util.DateUtils;
import com.google.android.collect.Lists;
@@ -65,7 +64,8 @@
@Override
protected DataKind addDataKindStructuredName(Context context) {
DataKind kind = addKind(new DataKind(StructuredName.CONTENT_ITEM_TYPE,
- R.string.nameLabelsGroup, -1, -1, true));
+ R.string.nameLabelsGroup, -1, -1, true,
+ R.layout.structured_name_editor_view, android.R.style.TextAppearance_Large, -1));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -94,7 +94,8 @@
@Override
protected DataKind addDataKindDisplayName(Context context) {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME,
- R.string.nameLabelsGroup, -1, -1, true));
+ R.string.nameLabelsGroup, -1, -1, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Large, -1));
boolean displayOrderPrimary =
context.getResources().getBoolean(R.bool.config_editor_field_order_primary);
@@ -127,7 +128,8 @@
@Override
protected DataKind addDataKindPhoneticName(Context context) {
DataKind kind = addKind(new DataKind(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME,
- R.string.name_phonetic, -1, -1, true));
+ R.string.name_phonetic, -1, -1, true,
+ R.layout.phonetic_name_editor_view, android.R.style.TextAppearance_Medium, -1));
kind.actionHeader = new SimpleInflater(R.string.nameLabelsGroup);
kind.actionBody = new SimpleInflater(Nickname.NAME);
@@ -292,7 +294,9 @@
protected DataKind addDataKindEvent(Context context) {
DataKind kind = addKind(
- new DataKind(Event.CONTENT_ITEM_TYPE, R.string.eventLabelsGroup, -1, 150, true));
+ new DataKind(Event.CONTENT_ITEM_TYPE, R.string.eventLabelsGroup, -1, 150, true,
+ R.layout.event_field_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_event));
kind.actionHeader = new EventActionInflater();
kind.actionBody = new SimpleInflater(Event.START_DATE);
@@ -303,7 +307,6 @@
kind.typeList.add(buildEventType(Event.TYPE_BIRTHDAY, false).setSpecificMax(1));
kind.dateFormatWithYear = DateUtils.DATE_AND_TIME_FORMAT;
- kind.editorClass = EventFieldEditorView.class;
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(Event.DATA, R.string.eventLabelsGroup, FLAGS_EVENT));
diff --git a/src/com/android/contacts/model/GoogleAccountType.java b/src/com/android/contacts/model/GoogleAccountType.java
index af25691..bd445b1 100644
--- a/src/com/android/contacts/model/GoogleAccountType.java
+++ b/src/com/android/contacts/model/GoogleAccountType.java
@@ -17,7 +17,6 @@
package com.android.contacts.model;
import com.android.contacts.R;
-import com.android.contacts.editor.EventFieldEditorView;
import com.android.contacts.util.DateUtils;
import com.google.android.collect.Lists;
@@ -63,9 +62,10 @@
kind.typeColumn = Phone.TYPE;
kind.typeList = Lists.newArrayList();
- kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
kind.typeList.add(buildPhoneType(Phone.TYPE_WORK));
+ kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));
+ kind.typeList.add(buildPhoneType(Phone.TYPE_MAIN));
kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_WORK).setSecondary(true));
kind.typeList.add(buildPhoneType(Phone.TYPE_FAX_HOME).setSecondary(true));
kind.typeList.add(buildPhoneType(Phone.TYPE_PAGER).setSecondary(true));
@@ -99,7 +99,9 @@
private DataKind addDataKindRelation(Context context) {
DataKind kind = addKind(new DataKind(Relation.CONTENT_ITEM_TYPE,
- R.string.relationLabelsGroup, -1, 160, true));
+ R.string.relationLabelsGroup, -1, 160, true,
+ R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_relationship));
kind.actionHeader = new RelationActionInflater();
kind.actionBody = new SimpleInflater(Relation.NAME);
@@ -134,10 +136,11 @@
private DataKind addDataKindEvent(Context context) {
DataKind kind = addKind(new DataKind(Event.CONTENT_ITEM_TYPE,
- R.string.eventLabelsGroup, -1, 150, true));
+ R.string.eventLabelsGroup, -1, 150, true,
+ R.layout.event_field_editor_view, android.R.style.TextAppearance_Medium,
+ R.string.add_event));
kind.actionHeader = new EventActionInflater();
kind.actionBody = new SimpleInflater(Event.START_DATE);
- kind.editorClass = EventFieldEditorView.class;
kind.typeColumn = Event.TYPE;
kind.typeList = Lists.newArrayList();
diff --git a/src/com/android/contacts/preference/ContactsPreferenceActivity.java b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
index 7f7b750..0b1970e 100644
--- a/src/com/android/contacts/preference/ContactsPreferenceActivity.java
+++ b/src/com/android/contacts/preference/ContactsPreferenceActivity.java
@@ -17,7 +17,7 @@
package com.android.contacts.preference;
import com.android.contacts.R;
-import com.android.contacts.activities.ContactBrowserActivity;
+import com.android.contacts.activities.PeopleActivity;
import android.app.ActionBar;
import android.content.Context;
@@ -66,7 +66,7 @@
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: {
- Intent intent = new Intent(this, ContactBrowserActivity.class);
+ Intent intent = new Intent(this, PeopleActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index bd59856..787d482 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -2,7 +2,7 @@
import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DataKind;
+import com.android.contacts.model.DataKind;
import com.android.contacts.util.Constants;
import com.android.contacts.util.PhoneCapabilityTester;
diff --git a/src/com/android/contacts/quickcontact/FloatingChildLayout.java b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
new file mode 100644
index 0000000..ddba609
--- /dev/null
+++ b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.quickcontact;
+
+import com.android.contacts.R;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.Animation.AnimationListener;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.PopupWindow;
+
+/**
+ * Layout containing single child {@link View} which it attempts to center
+ * around {@link #setChildTargetScreen(Rect)}.
+ * <p>
+ * Updates drawable state to be {@link android.R.attr#state_first} when child is
+ * above target, and {@link android.R.attr#state_last} when child is below
+ * target. Also updates {@link Drawable#setLevel(int)} on child
+ * {@link View#getBackground()} to reflect horizontal center of target.
+ * <p>
+ * The reason for this approach is because target {@link Rect} is in screen
+ * coordinates disregarding decor insets; otherwise something like
+ * {@link PopupWindow} might work better.
+ */
+public class FloatingChildLayout extends FrameLayout {
+ private static final String TAG = "FloatingChild";
+
+ public FloatingChildLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ private View mChild;
+
+ private Rect mTargetScreen = new Rect();
+
+ private int mCalloutState = 0;
+ private int mCalloutLeft;
+
+ @Override
+ protected void onFinishInflate() {
+ mChild = findViewById(android.R.id.content);
+ mChild.setDuplicateParentStateEnabled(true);
+ }
+
+ public View getChild() {
+ return mChild;
+ }
+
+ /**
+ * Set {@link Rect} in screen coordinates that {@link #getChild()} should be
+ * centered around.
+ */
+ public void setChildTargetScreen(Rect targetScreen) {
+ mTargetScreen = targetScreen;
+ requestLayout();
+ }
+
+ /**
+ * Return {@link #mTargetScreen} in local window coordinates, taking any
+ * decor insets into account.
+ */
+ private Rect getTargetInWindow() {
+ final Rect windowScreen = new Rect();
+ getWindowVisibleDisplayFrame(windowScreen);
+
+ final Rect target = new Rect(mTargetScreen);
+ target.offset(-windowScreen.left, -windowScreen.top);
+ return target;
+ }
+
+ private void updateCallout(int calloutState, int calloutLeft) {
+ if (mCalloutState != calloutState) {
+ mCalloutState = calloutState;
+ mChild.refreshDrawableState();
+ }
+
+ final Drawable background = mChild.getBackground();
+ if (background != null && mCalloutLeft != calloutLeft) {
+ mCalloutLeft = calloutLeft;
+ background.setLevel(calloutLeft);
+ }
+ }
+
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+ mergeDrawableStates(drawableState, new int[] { mCalloutState });
+ return drawableState;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+
+ final View child = mChild;
+ final Rect target = getTargetInWindow();
+
+ final int childWidth = child.getMeasuredWidth();
+ final int childHeight = child.getMeasuredHeight();
+
+ // default is no callout, left-aligned, and vertically centered
+ int calloutState = 0;
+ int childLeft = target.left;
+ int childTop = target.centerY() - (childHeight / 2);
+
+ // when target is wide, horizontally center instead of left-align
+ if (target.width() > childWidth / 2) {
+ childLeft = target.centerX() - (childWidth / 2);
+ }
+
+ final int areaAboveTarget = target.top;
+ final int areaBelowTarget = getHeight() - target.bottom;
+
+ if (areaAboveTarget >= childHeight) {
+ // enough room above target, place above and callout down
+ calloutState = android.R.attr.state_first;
+ childTop = target.top - childHeight;
+
+ } else if (areaBelowTarget >= childHeight) {
+ // enough room below target, place below and callout up
+ calloutState = android.R.attr.state_last;
+ childTop = target.bottom;
+ }
+
+ // when child is outside bounds, nudge back inside
+ childLeft = clampDimension(childLeft, childWidth, getWidth());
+ childTop = clampDimension(childTop, childHeight, getHeight());
+
+ final int calloutLeft = target.centerX() - childLeft;
+ updateCallout(calloutState, calloutLeft);
+ layoutChild(child, childLeft, childTop);
+
+ }
+
+ private static int clampDimension(int value, int size, int max) {
+ // when larger than bounds, just center
+ if (size > max) {
+ return (max - size) / 2;
+ }
+
+ // clamp to lower bound
+ value = Math.max(value, 0);
+ // clamp to higher bound
+ value = Math.min(value, max - size);
+
+ return value;
+ }
+
+ private static void layoutChild(View child, int left, int top) {
+ child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
+ }
+
+ /**
+ * Begin animating {@link #getChild()} visible.
+ */
+ public void showChild() {
+ final boolean calloutAbove = mCalloutState == android.R.attr.state_first;
+ final Animation anim = AnimationUtils.loadAnimation(getContext(),
+ calloutAbove ? R.anim.quickcontact_above_enter : R.anim.quickcontact_below_enter);
+ mChild.startAnimation(anim);
+ mChild.setVisibility(View.VISIBLE);
+ }
+
+ /**
+ * Begin animating {@link #getChild()} invisible.
+ */
+ public void hideChild(final Runnable onAnimationEnd) {
+ final boolean calloutAbove = mCalloutState == android.R.attr.state_first;
+ final Animation anim = AnimationUtils.loadAnimation(getContext(),
+ calloutAbove ? R.anim.quickcontact_above_exit : R.anim.quickcontact_below_exit);
+
+ if (onAnimationEnd != null) {
+ anim.setAnimationListener(new AnimationListener() {
+ /** {@inheritDoc} */
+ public void onAnimationStart(Animation animation) {
+ // ignored
+ }
+
+ /** {@inheritDoc} */
+ public void onAnimationRepeat(Animation animation) {
+ // ignored
+ }
+
+ /** {@inheritDoc} */
+ public void onAnimationEnd(Animation animation) {
+ onAnimationEnd.run();
+ }
+ });
+ }
+
+ mChild.startAnimation(anim);
+ mChild.setVisibility(View.INVISIBLE);
+ }
+
+ private View.OnTouchListener mOutsideTouchListener;
+
+ public void setOnOutsideTouchListener(View.OnTouchListener listener) {
+ mOutsideTouchListener = listener;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // at this point, touch wasn't handled by child view; assume outside
+ if (mOutsideTouchListener != null) {
+ return mOutsideTouchListener.onTouch(this, event);
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
deleted file mode 100644
index 5032386..0000000
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.quickcontact;
-
-import com.android.contacts.ContactsActivity;
-
-import android.content.ContentUris;
-import android.content.Intent;
-import android.graphics.Rect;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.QuickContact;
-import android.provider.ContactsContract.RawContacts;
-import android.util.Log;
-
-/**
- * Stub translucent activity that just shows {@link QuickContactWindow} floating
- * above the caller. This temporary hack should eventually be replaced with
- * direct framework support.
- */
-public final class QuickContactActivity extends ContactsActivity
- implements QuickContactWindow.OnDismissListener {
- private static final String TAG = "QuickContactActivity";
-
- static final boolean LOGV = false;
- static final boolean FORCE_CREATE = true;
-
- private QuickContactWindow mQuickContact;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- if (LOGV) Log.d(TAG, "onCreate");
-
- 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
- Uri lookupUri = intent.getData();
- // Check to see whether it comes from the old version.
- if (android.provider.Contacts.AUTHORITY.equals(lookupUri.getAuthority())) {
- final long rawContactId = ContentUris.parseId(lookupUri);
- lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
- }
- final Bundle extras = intent.getExtras();
-
- // Read requested parameters for displaying
- final Rect target = intent.getSourceBounds();
- final int mode = extras.getInt(QuickContact.EXTRA_MODE, QuickContact.MODE_MEDIUM);
- final String[] excludeMimes = extras.getStringArray(QuickContact.EXTRA_EXCLUDE_MIMES);
-
- mQuickContact.show(lookupUri, target, mode, excludeMimes);
- }
-
- /** {@inheritDoc} */
- @Override
- 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");
-
- // Dismiss any dialog when pausing
- mQuickContact.dismiss();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- if (LOGV) Log.d(TAG, "onDestroy");
- }
-
- /** {@inheritDoc} */
- @Override
- public void onDismiss(QuickContactWindow dialog) {
- if (LOGV) Log.d(TAG, "onDismiss");
-
- if (isTaskRoot() && !FORCE_CREATE) {
- // 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/quickcontact/QuickContactBackgroundDrawable.java b/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java
index 9118480..15311f9 100644
--- a/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java
+++ b/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java
@@ -26,37 +26,43 @@
import android.graphics.drawable.Drawable;
/**
- * Drawable that draws three pictures for the QuickContact-Background. ColorFilter is ignored
+ * Background {@link Drawable} for {@link QuickContactWindow} that draws arrow
+ * centered around requested position.
*/
public class QuickContactBackgroundDrawable extends Drawable {
private Drawable mLeftDrawable;
private Drawable mMiddleDrawable;
private Drawable mRightDrawable;
- private int mRequestedX = Integer.MIN_VALUE;
- private boolean mBoundsSet = false;
- private int mAlpha = -1;
+
private int mBottomOverride = Integer.MIN_VALUE;
+ public QuickContactBackgroundDrawable(Resources res) {
+ mLeftDrawable = res.getDrawable(R.drawable.quickactions_arrow_left_holo_light);
+ mMiddleDrawable = res.getDrawable(R.drawable.quickactions_arrow_middle_holo_light);
+ mRightDrawable = res.getDrawable(R.drawable.quickactions_arrow_right_holo_light);
+ }
+
@Override
public void setAlpha(int alpha) {
- mAlpha = alpha;
- setChildAlpha();
+ mLeftDrawable.setAlpha(alpha);
+ mMiddleDrawable.setAlpha(alpha);
+ mRightDrawable.setAlpha(alpha);
}
/**
- * Overrides the bottom bounds. This is used for the animation when the QuickContact
- * expands/collapses options
+ * Overrides the bottom bounds. This is used for the animation when the
+ * QuickContact expands/collapses options
*/
public void setBottomOverride(int value) {
mBottomOverride = value;
- setChildBounds();
+ onBoundsChange(getBounds());
invalidateSelf();
}
public void clearBottomOverride() {
mBottomOverride = Integer.MIN_VALUE;
+ onBoundsChange(getBounds());
invalidateSelf();
- setChildBounds();
}
public float getBottomOverride() {
@@ -64,7 +70,29 @@
}
@Override
+ public boolean isStateful() {
+ return true;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ super.onStateChange(state);
+ mLeftDrawable.setState(state);
+ mMiddleDrawable.setState(state);
+ mRightDrawable.setState(state);
+ return true;
+ }
+
+ @Override
+ protected boolean onLevelChange(int level) {
+ return true;
+ }
+
+ @Override
public void setColorFilter(ColorFilter cf) {
+ mLeftDrawable.setColorFilter(cf);
+ mMiddleDrawable.setColorFilter(cf);
+ mRightDrawable.setColorFilter(cf);
}
@Override
@@ -72,54 +100,22 @@
return PixelFormat.TRANSLUCENT;
}
- public void configure(Resources resources, boolean arrowUp, int requestedX) {
- mLeftDrawable = resources.getDrawable(arrowUp
- ? R.drawable.quickactions_arrowup_left_holo_light
- : R.drawable.quickactions_arrowdown_left_holo_light);
- mMiddleDrawable = resources.getDrawable(arrowUp
- ? R.drawable.quickactions_arrowup_middle_holo_light
- : R.drawable.quickactions_arrowdown_middle_holo_light);
- mRightDrawable = resources.getDrawable(arrowUp
- ? R.drawable.quickactions_arrowup_right_holo_light
- : R.drawable.quickactions_arrowdown_right_holo_light);
-
- mRequestedX = requestedX;
-
- setChildAlpha();
- setChildBounds();
- }
-
@Override
protected void onBoundsChange(Rect bounds) {
- mBoundsSet = true;
- setChildBounds();
- }
+ final int requestedX = getLevel();
- private void setChildAlpha() {
- if (mAlpha == -1) return;
-
- if (mLeftDrawable != null) mLeftDrawable.setAlpha(mAlpha);
- if (mMiddleDrawable != null) mMiddleDrawable.setAlpha(mAlpha);
- if (mRightDrawable != null) mRightDrawable.setAlpha(mAlpha);
- }
-
- private void setChildBounds() {
- if (mRequestedX == Integer.MIN_VALUE) return;
- if (!mBoundsSet) return;
-
- final Rect bounds = getBounds();
- int middleLeft = mRequestedX - mMiddleDrawable.getIntrinsicWidth() / 2;
- int middleRight = mRequestedX + mMiddleDrawable.getIntrinsicWidth() / 2;
+ int middleLeft = requestedX - mMiddleDrawable.getIntrinsicWidth() / 2;
+ int middleRight = requestedX + mMiddleDrawable.getIntrinsicWidth() / 2;
// ensure left drawable is not smaller than its Intrinsic Width
- final int leftExtra = (middleLeft - bounds.left) - mLeftDrawable.getIntrinsicWidth();
+ final int leftExtra = (middleLeft - bounds.left) - mLeftDrawable.getIntrinsicWidth();
if (leftExtra < 0) {
middleLeft -= leftExtra;
middleRight -= leftExtra;
}
// ensure right drawable is not smaller than its Intrinsic Width
- final int rightExtra = (bounds.right - middleRight) - mRightDrawable.getIntrinsicWidth();
+ final int rightExtra = (bounds.right - middleRight) - mRightDrawable.getIntrinsicWidth();
if (rightExtra < 0) {
middleLeft += rightExtra;
middleRight += rightExtra;
diff --git a/src/com/android/contacts/quickcontact/QuickContactRootLayout.java b/src/com/android/contacts/quickcontact/QuickContactRootLayout.java
deleted file mode 100644
index 007783a..0000000
--- a/src/com/android/contacts/quickcontact/QuickContactRootLayout.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts.quickcontact;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.LinearLayout;
-
-/**
- * Custom layout for Quick Contact. It intercepts the BACK key and
- * close QC even when the soft keyboard is open.
- */
-public class QuickContactRootLayout extends LinearLayout {
- private Listener mListener;
-
- public QuickContactRootLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public void setListener(Listener value) {
- mListener = value;
- }
-
- /**
- * Intercepts the BACK key event and dismisses QuickContact window.
- */
- @Override
- public boolean dispatchKeyEventPreIme(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
- if (mListener != null) mListener.onBackPressed();
- return true;
- }
- return super.dispatchKeyEventPreIme(event);
- }
-
- public interface Listener {
- void onBackPressed();
- }
-}
diff --git a/src/com/android/contacts/quickcontact/QuickContactWindow.java b/src/com/android/contacts/quickcontact/QuickContactWindow.java
index a66f506..5f4bcc9 100644
--- a/src/com/android/contacts/quickcontact/QuickContactWindow.java
+++ b/src/com/android/contacts/quickcontact/QuickContactWindow.java
@@ -20,18 +20,20 @@
import com.android.contacts.ContactPresenceIconUtil;
import com.android.contacts.ContactSaveService;
import com.android.contacts.R;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
import com.android.contacts.util.Constants;
import com.android.contacts.util.DataStatus;
import com.android.contacts.util.NotifyingAsyncQueryHandler;
-import com.android.internal.policy.PolicyManager;
import com.google.android.collect.Lists;
+import com.google.common.base.Preconditions;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.app.Activity;
import android.content.ActivityNotFoundException;
+import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -41,6 +43,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Bundle;
import android.os.Handler;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Im;
@@ -54,31 +57,16 @@
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.util.Log;
-import android.view.ActionMode;
-import android.view.ContextThemeWrapper;
-import android.view.Gravity;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewStub;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityEvent;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -89,72 +77,44 @@
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 QuickContact dialog for a specific {@link Contacts#_ID}.
+ * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads
+ * data asynchronously, and then shows a popup with details centered around
+ * {@link Intent#getSourceBounds()}.
*/
-public class QuickContactWindow implements Window.Callback,
+public class QuickContactWindow extends Activity implements
NotifyingAsyncQueryHandler.AsyncQueryListener, View.OnClickListener,
- AbsListView.OnItemClickListener, KeyEvent.Callback, OnGlobalLayoutListener,
- QuickContactRootLayout.Listener {
+ AbsListView.OnItemClickListener {
+ private static final String TAG = "QuickContact";
- private static final String TAG = "QuickContactWindow";
+ private static final boolean TRACE_LAUNCH = false;
+ private static final String TRACE_TAG = "quickcontact";
- /**
- * Interface used to allow the person showing a {@link QuickContactWindow} to
- * know when the window has been dismissed.
- */
- public interface OnDismissListener {
- public void onDismiss(QuickContactWindow dialog);
- }
-
- private final static int ANIMATION_FADE_IN_TIME = 100;
- private final static int ANIMATION_FADE_OUT_TIME = 100;
- private final static int ANIMATION_EXPAND_TIME = 100;
- private final static int ANIMATION_COLLAPSE_TIME = 100;
-
- /**
- * If the anchor is wider than (quick contact width * this constant) then
- * center quick contact. Otherwise, left-align.
- */
- private static final double MIN_RELATIVE_ANCHOR_WIDTH_TO_CENTER = 0.5;
-
- private final Context mContext;
- private final LayoutInflater mInflater;
- private final WindowManager mWindowManager;
- private Window mWindow;
- private View mDecor;
- private final Rect mRect = new Rect();
-
- private boolean mDismissed = false;
- private boolean mQuerying = false;
- private boolean mShowing = false;
+ private static final int ANIMATION_FADE_IN_TIME = 100;
+ private static final int ANIMATION_FADE_OUT_TIME = 100;
+ private static final int ANIMATION_EXPAND_TIME = 100;
+ private static final int ANIMATION_COLLAPSE_TIME = 100;
private NotifyingAsyncQueryHandler mHandler;
- private OnDismissListener mDismissListener;
private Uri mLookupUri;
- private Rect mAnchor;
-
- private int mScreenWidth;
- private int mUseableScreenHeight;
- private int mRequestedY;
+ private int mMode;
+ private String[] mExcludeMimes;
private boolean mHasValidSocial = false;
- private int mMode;
- private QuickContactRootLayout mRootView;
+ private FloatingChildLayout mFloatingLayout;
private QuickContactBackgroundDrawable mBackground;
- private View mHeader;
- private HorizontalScrollView mTrackScroll;
- private ViewGroup mTrack;
+ private View mHeader;
+ private ViewGroup mTrack;
private FrameLayout mFooter;
private LinearLayout mFooterDisambig;
private LinearLayout mFooterClearDefaults;
+
private ListView mResolveList;
private CheckableImageView mLastAction;
private CheckBox mSetPrimaryCheckBox;
@@ -166,9 +126,6 @@
*/
private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>();
- private int mWindowRecycled = 0;
- private int mActionRecycled = 0;
-
/**
* Set of {@link Action} that are associated with the aggregate currently
* displayed by this dialog, represented as a map from {@link String}
@@ -177,14 +134,6 @@
private ActionMultiMap mActions = new ActionMultiMap();
/**
- * Pool of unused {@link CheckableImageView} that have previously been
- * inflated, and are ready to be recycled through {@link #obtainView()}.
- */
- private LinkedList<CheckableImageView> mActionPool = new LinkedList<CheckableImageView>();
-
- private String[] mExcludeMimes;
-
- /**
* {@link #PRECEDING_MIMETYPES} and {@link #FOLLOWING_MIMETYPES} are used to sort MIME-types.
*
* <p>The MIME-types in {@link #PRECEDING_MIMETYPES} appear in the front of the dialog,
@@ -222,80 +171,48 @@
});
private static final int TOKEN_DATA = 1;
- static final boolean TRACE_LAUNCH = false;
- static final String TRACE_TAG = "quickcontact";
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
- /**
- * Prepare a dialog to show in the given {@link Context}.
- */
- public QuickContactWindow(Context context) {
- mContext = new ContextThemeWrapper(context, R.style.QuickContact);
- mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+ setContentView(R.layout.quickcontact_activity);
- mWindow = PolicyManager.makeNewWindow(mContext);
- mWindow.setCallback(this);
- mWindow.setWindowManager(mWindowManager, null, null);
- mWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED);
+ mBackground = new QuickContactBackgroundDrawable(getResources());
- mWindow.setContentView(R.layout.quickcontact);
+ mFloatingLayout = findTypedViewById(R.id.floating_layout);
+ mFloatingLayout.getChild().setBackgroundDrawable(mBackground);
+ mFloatingLayout.setOnOutsideTouchListener(mOnOutsideTouchListener);
- mRootView = (QuickContactRootLayout)mWindow.findViewById(R.id.root);
- mRootView.setListener(this);
- mRootView.setFocusable(true);
- mRootView.setFocusableInTouchMode(true);
- mRootView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
+ mTrack = findTypedViewById(R.id.quickcontact);
+ mFooter = findTypedViewById(R.id.footer);
+ mFooterDisambig = findTypedViewById(R.id.footer_disambig);
+ mFooterClearDefaults = findTypedViewById(R.id.footer_clear_defaults);
+ mResolveList = findTypedViewById(android.R.id.list);
+ mSetPrimaryCheckBox = findTypedViewById(android.R.id.checkbox);
- mBackground = new QuickContactBackgroundDrawable();
- mRootView.setBackgroundDrawable(mBackground);
+ mDefaultsListView = findTypedViewById(R.id.defaults_list);
- final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
- mScreenWidth = metrics.widthPixels;
- mUseableScreenHeight = metrics.heightPixels;
+ mClearDefaultsButton = findTypedViewById(R.id.clear_defaults_button);
+ mClearDefaultsButton.setOnClickListener(mOnClearDefaultsClickListener);
- mTrack = (ViewGroup) mWindow.findViewById(R.id.quickcontact);
- mTrackScroll = (HorizontalScrollView) mWindow.findViewById(R.id.scroll);
+ mResolveList.setOnItemClickListener(this);
- mFooter = (FrameLayout) mWindow.findViewById(R.id.footer);
- mFooterDisambig = (LinearLayout) mWindow.findViewById(R.id.footer_disambig);
- mFooterClearDefaults = (LinearLayout) mWindow.findViewById(R.id.footer_clear_defaults);
- mResolveList = (ListView) mWindow.findViewById(android.R.id.list);
- mSetPrimaryCheckBox = (CheckBox) mWindow.findViewById(android.R.id.checkbox);
+ mHandler = new NotifyingAsyncQueryHandler(this, this);
- mDefaultsListView = (ListView) mWindow.findViewById(R.id.defaults_list);
- mClearDefaultsButton = (Button) mWindow.findViewById(R.id.clear_defaults_button);
- mClearDefaultsButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- clearDefaults();
- }
- });
-
- mResolveList.setOnItemClickListener(QuickContactWindow.this);
-
- mHandler = new NotifyingAsyncQueryHandler(mContext, this);
- }
-
- /**
- * 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);
- mDismissListener = dismissListener;
+ show();
}
private View getHeaderView(int mode) {
View header = null;
switch (mode) {
case QuickContact.MODE_SMALL:
- header = mWindow.findViewById(R.id.header_small);
+ header = findViewById(R.id.header_small);
break;
case QuickContact.MODE_MEDIUM:
- header = mWindow.findViewById(R.id.header_medium);
+ header = findViewById(R.id.header_medium);
break;
case QuickContact.MODE_LARGE:
- header = mWindow.findViewById(R.id.header_large);
+ header = findViewById(R.id.header_large);
break;
}
@@ -310,60 +227,52 @@
return header;
}
- /**
- * Start showing a dialog for the given {@link Contacts#_ID} pointing
- * towards the given location.
- */
- public synchronized void show(Uri lookupUri, Rect anchor, int mode, String[] excludeMimes) {
- if (mQuerying || mShowing) {
- Log.w(TAG, "dismissing before showing");
- dismissInternal();
- }
+ private void show() {
- if (TRACE_LAUNCH && !android.os.Debug.isMethodTracingActive()) {
+ if (TRACE_LAUNCH) {
android.os.Debug.startMethodTracing(TRACE_TAG);
}
- // Validate incoming parameters
- final boolean validMode = (mode == QuickContact.MODE_SMALL
- || mode == QuickContact.MODE_MEDIUM || mode == QuickContact.MODE_LARGE);
- if (!validMode) {
- throw new IllegalArgumentException("Invalid mode, expecting MODE_LARGE, "
- + "MODE_MEDIUM, or MODE_SMALL");
+ final Intent intent = getIntent();
+
+ Uri lookupUri = intent.getData();
+
+ // Check to see whether it comes from the old version.
+ if (android.provider.Contacts.AUTHORITY.equals(lookupUri.getAuthority())) {
+ final long rawContactId = ContentUris.parseId(lookupUri);
+ lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
}
- if (anchor == null) {
- throw new IllegalArgumentException("Missing anchor rectangle");
+ mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri");
+
+ // Read requested parameters for displaying
+ final Rect targetScreen = intent.getSourceBounds();
+ Preconditions.checkNotNull(targetScreen, "missing targetScreen");
+ mFloatingLayout.setChildTargetScreen(targetScreen);
+
+ mMode = intent.getIntExtra(QuickContact.EXTRA_MODE, QuickContact.MODE_MEDIUM);
+ mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
+
+ switch (mMode) {
+ case QuickContact.MODE_SMALL:
+ case QuickContact.MODE_MEDIUM:
+ case QuickContact.MODE_LARGE:
+ break;
+ default:
+ throw new IllegalArgumentException("Unexpected mode: " + mMode);
}
- // Prepare header view for requested mode
- mLookupUri = lookupUri;
- mAnchor = new Rect(anchor);
- mMode = mode;
- mExcludeMimes = excludeMimes;
-
- mHeader = getHeaderView(mode);
-
+ // find and prepare correct header view
+ mHeader = getHeaderView(mMode);
setHeaderText(R.id.name, R.string.quickcontact_missing_name);
-
setHeaderText(R.id.status, null);
setHeaderText(R.id.timestamp, null);
-
setHeaderImage(R.id.presence, null);
- resetTrack();
-
- // We need to have a focused view inside the QuickContact window so
- // that the BACK key event can be intercepted
- mRootView.requestFocus();
-
- mHasValidSocial = false;
- mDismissed = false;
- mQuerying = true;
-
// Start background query for data, but only select photo rows when they
// directly match the super-primary PHOTO_ID.
- final Uri dataUri = getDataUri(lookupUri);
+ final Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY);
mHandler.cancelOperation(TOKEN_DATA);
// Only request photo data when required by mode
@@ -379,222 +288,85 @@
}
}
- /**
- * 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) {
- return Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY);
+ @SuppressWarnings("unchecked")
+ private <T> T findTypedViewById(int id) {
+ return (T) super.findViewById(id);
}
- /**
- * Creates and configures the background resource
- */
- private void configureBackground(boolean arrowUp, int requestedX) {
- mBackground.configure(mContext.getResources(), arrowUp, requestedX);
+ private View.OnTouchListener mOnOutsideTouchListener = new View.OnTouchListener() {
+ /** {@inheritDoc} */
+ public boolean onTouch(View v, MotionEvent event) {
+ hide(true);
+ return true;
+ }
+ };
+
+ private View.OnClickListener mOnClearDefaultsClickListener = new View.OnClickListener() {
+ /** {@inheritDoc} */
+ public void onClick(View v) {
+ clearDefaults();
+ }
+ };
+
+ private void hide(boolean withAnimation) {
+ // cancel any pending queries
+ mHandler.cancelOperation(TOKEN_DATA);
+
+ if (withAnimation) {
+ mFloatingLayout.hideChild(new Runnable() {
+ /** {@inheritDoc} */
+ public void run() {
+ finish();
+ }
+ });
+ } else {
+ mFloatingLayout.hideChild(null);
+ finish();
+ }
}
- /**
- * Actual internal method to show this dialog. Called only by
- * {@link #considerShowing()} when all data requirements have been met.
- */
- private void showInternal() {
- mDecor = mWindow.getDecorView();
- mDecor.getViewTreeObserver().addOnGlobalLayoutListener(this);
- WindowManager.LayoutParams layoutParams = mWindow.getAttributes();
-
- layoutParams.width = mContext.getResources().getDimensionPixelSize(
- R.dimen.quick_contact_width);
- layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
-
- // Try to left align with the anchor control or center if the anchor is wide
- if (mAnchor.left + layoutParams.width <= mScreenWidth) {
- if (mAnchor.width() > layoutParams.width * MIN_RELATIVE_ANCHOR_WIDTH_TO_CENTER) {
- layoutParams.x = mAnchor.left + (mAnchor.width() - layoutParams.width) / 2;
- } else {
- layoutParams.x = mAnchor.left;
- }
- } else {
- // Not enough space. Try to right align to the anchor
- if (mAnchor.right - layoutParams.width >= 0) {
- layoutParams.x = mAnchor.right - layoutParams.width;
- } else {
- // Also not enough space. Use the whole screen width available
- layoutParams.x = 0;
- layoutParams.width = mScreenWidth;
- }
- }
-
- // Force layout measuring pass so we have baseline numbers
- mDecor.measure(layoutParams.width, layoutParams.height);
- final int blockHeight = mDecor.getMeasuredHeight();
-
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
-
- if (mUseableScreenHeight - mAnchor.bottom > blockHeight) {
- // Show downwards callout when enough room, aligning block top with bottom of
- // anchor area, and adjusting to inset arrow.
- configureBackground(true, mAnchor.centerX() - layoutParams.x);
- layoutParams.y = mAnchor.bottom;
- layoutParams.windowAnimations = R.style.QuickContactBelowAnimation;
- } else {
- // Show upwards callout, aligning bottom block
- // edge with top of anchor area, and adjusting to inset arrow.
- configureBackground(false, mAnchor.centerX() - layoutParams.x);
- layoutParams.y = mAnchor.top - blockHeight;
- layoutParams.windowAnimations = R.style.QuickContactAboveAnimation;
- }
-
- layoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
-
- mRequestedY = layoutParams.y;
- mWindowManager.addView(mDecor, layoutParams);
- mShowing = true;
- mQuerying = false;
- mDismissed = false;
-
- if (TRACE_LAUNCH) {
- android.os.Debug.stopMethodTracing();
- Log.d(TAG, "Window recycled " + mWindowRecycled + " times, chiclets "
- + mActionRecycled + " times");
- }
+ @Override
+ public void onBackPressed() {
+ hide(true);
}
/** {@inheritDoc} */
- @Override
- public void onGlobalLayout() {
- layoutInScreen();
- }
+ public synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ try {
+ if (isFinishing()) {
+ hide(false);
+ return;
+ } else if (cursor == null || cursor.getCount() == 0) {
+ Toast.makeText(this, R.string.invalidContactMessage, Toast.LENGTH_LONG).show();
+ hide(false);
+ return;
+ }
- /**
- * Adjust vertical {@link WindowManager.LayoutParams} to fit window as best
- * as possible, shifting up to display content as needed.
- */
- private void layoutInScreen() {
- if (!mShowing) return;
+ bindData(cursor);
- final WindowManager.LayoutParams l = mWindow.getAttributes();
- final int originalY = l.y;
-
- final int blockHeight = mDecor.getHeight();
-
- l.y = mRequestedY;
- if (mRequestedY + blockHeight > mUseableScreenHeight) {
- // Shift up from bottom when overflowing
- l.y = mUseableScreenHeight - blockHeight;
- }
-
- if (originalY != l.y) {
- // Only update when value is changed
- mWindow.setAttributes(l);
- }
- }
-
- /**
- * Dismiss this dialog if showing.
- */
- public synchronized void dismiss() {
- // Notify any listeners that we've been dismissed
- if (mDismissListener != null) {
- mDismissListener.onDismiss(this);
- }
-
- dismissInternal();
- }
-
- private void dismissInternal() {
- // Remove any attached window decor for recycling
- boolean hadDecor = mDecor != null;
- if (hadDecor) {
- mWindowManager.removeView(mDecor);
- mWindowRecycled++;
- mDecor.getViewTreeObserver().removeGlobalOnLayoutListener(this);
- mDecor = null;
- mWindow.closeAllPanels();
- }
- mShowing = false;
- mDismissed = true;
-
- // Cancel any pending queries
- mHandler.cancelOperation(TOKEN_DATA);
- mQuerying = false;
-
- // Completely hide header and reset track
- mHeader.setVisibility(View.GONE);
- resetTrack();
- }
-
- /**
- * Reset track to initial state, recycling any chiclets.
- */
- private void resetTrack() {
- // Clear background height-animation override
- mBackground.clearBottomOverride();
-
- // Release reference to last chiclet
- mLastAction = null;
-
- // Clear track actions and scroll to hard left
- mActions.clear();
-
- // Recycle any chiclets in use
- for (int i = mTrack.getChildCount() - 1; i >= 0; i--) {
- releaseView((CheckableImageView)mTrack.getChildAt(i));
- mTrack.removeViewAt(i);
- }
-
- mTrackScroll.fullScroll(View.FOCUS_LEFT);
-
- // Clear any primary requests
- mSetPrimaryCheckBox.setChecked(false);
-
- setNewActionViewChecked(null);
- mFooter.setVisibility(View.GONE);
- }
-
- /**
- * Consider showing this window, which will only call through to
- * {@link #showInternal()} when all data items are present.
- */
- private void considerShowing() {
- if (!mShowing && !mDismissed) {
if (mMode == QuickContact.MODE_MEDIUM && !mHasValidSocial) {
// Missing valid social, swap medium for small header
mHeader.setVisibility(View.GONE);
mHeader = getHeaderView(QuickContact.MODE_SMALL);
}
- // All queries have returned, pull curtain
- showInternal();
+ if (TRACE_LAUNCH) {
+ android.os.Debug.stopMethodTracing();
+ }
+
+ // data bound and ready, pull curtain to show
+ mFloatingLayout.showChild();
+
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
}
}
- /** {@inheritDoc} */
- @Override
- public synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
- // Bail early when query is stale
- if (cookie != mLookupUri) return;
-
- if (cursor == null) {
- // Problem while running query, so bail without showing
- Log.w(TAG, "Missing cursor for token=" + token);
- this.dismiss();
- return;
- }
-
- handleData(cursor);
-
- if (!cursor.isClosed()) {
- cursor.close();
- }
-
- considerShowing();
- }
-
/** Assign this string to the view, if found in {@link #mHeader}. */
private void setHeaderText(int id, int resId) {
- setHeaderText(id, mContext.getResources().getText(resId));
+ setHeaderText(id, getText(resId));
}
/** Assign this string to the view, if found in {@link #mHeader}. */
@@ -632,26 +404,22 @@
/**
* Handle the result from the {@link #TOKEN_DATA} query.
*/
- private void handleData(Cursor cursor) {
- final ResolveCache cache = ResolveCache.getInstance(mContext);
- if (cursor == null) return;
- if (cursor.getCount() == 0) {
- Toast.makeText(mContext, R.string.invalidContactMessage, Toast.LENGTH_LONG).show();
- dismiss();
- return;
- }
+ private void bindData(Cursor cursor) {
+ final ResolveCache cache = ResolveCache.getInstance(this);
+ final Context context = this;
if (!isMimeExcluded(Contacts.CONTENT_ITEM_TYPE)) {
// Add the profile shortcut action
- final Action action = new ProfileAction(mContext, mLookupUri);
+ final Action action = new ProfileAction(context, mLookupUri);
mActions.put(Contacts.CONTENT_ITEM_TYPE, action);
}
mDefaultsMap.clear();
final DataStatus status = new DataStatus();
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mContext);
- final ImageView photoView = (ImageView)mHeader.findViewById(R.id.photo);
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
+ context.getApplicationContext());
+ final ImageView photoView = (ImageView) mHeader.findViewById(R.id.photo);
Bitmap photoBitmap = null;
while (cursor.moveToNext()) {
@@ -683,7 +451,7 @@
// Build an action for this data entry, find a mapping to a UI
// element, build its summary from the cursor, and collect it
// along with all others of this MIME-type.
- final Action action = new DataAction(mContext, mimeType, kind, dataId, cursor);
+ final Action action = new DataAction(context, mimeType, kind, dataId, cursor);
final boolean wasAdded = considerAdd(action, cache);
if (wasAdded) {
// Remember the default
@@ -695,7 +463,7 @@
// If phone number, also insert as text message action
if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && kind != null) {
- final DataAction action = new DataAction(mContext, Constants.MIME_TYPE_SMS_ADDRESS,
+ final DataAction action = new DataAction(context, Constants.MIME_TYPE_SMS_ADDRESS,
kind, dataId, cursor);
considerAdd(action, cache);
}
@@ -708,7 +476,7 @@
final DataKind imKind = accountTypes.getKindOrFallback(accountType,
Im.CONTENT_ITEM_TYPE);
if (imKind != null) {
- final DataAction action = new DataAction(mContext, Im.CONTENT_ITEM_TYPE, imKind,
+ final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
dataId, cursor);
considerAdd(action, cache);
isIm = true;
@@ -721,7 +489,7 @@
final DataKind imKind = accountTypes.getKindOrFallback(accountType,
Im.CONTENT_ITEM_TYPE);
if (imKind != null) {
- final DataAction chatAction = new DataAction(mContext,
+ final DataAction chatAction = new DataAction(context,
Constants.MIME_TYPE_VIDEO_CHAT, imKind, dataId, cursor);
considerAdd(chatAction, cache);
}
@@ -729,6 +497,11 @@
}
}
+ // Collapse Action Lists (remove e.g. duplicate e-mail addresses from different sources)
+ for (ArrayList<Action> actionChildren : mActions.values()) {
+ Collapser.collapseList(actionChildren);
+ }
+
// Make sure that we only display the "clear default" action if there
// are actually several items to chose from
boolean shouldDisplayClearDefaults = false;
@@ -750,7 +523,7 @@
final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE);
final int chatCapability = cursor.getInt(DataQuery.CONTACT_CHAT_CAPABILITY);
final Drawable statusIcon = ContactPresenceIconUtil.getChatCapabilityIcon(
- mContext, presence, chatCapability);
+ context, presence, chatCapability);
setHeaderText(R.id.name, name);
setHeaderImage(R.id.presence, statusIcon);
@@ -766,7 +539,7 @@
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));
+ setHeaderText(R.id.timestamp, status.getTimestampLabel(context));
}
// Turn our list of actions into UI elements
@@ -780,7 +553,7 @@
for (String mimeType : PRECEDING_MIMETYPES) {
if (containedTypes.contains(mimeType)) {
hasData = true;
- mTrack.addView(inflateAction(mimeType, cache));
+ mTrack.addView(inflateAction(mimeType, cache, mTrack));
containedTypes.remove(mimeType);
}
}
@@ -792,7 +565,7 @@
for (String mimeType : FOLLOWING_MIMETYPES) {
if (containedTypes.contains(mimeType)) {
hasData = true;
- mTrack.addView(inflateAction(mimeType, cache));
+ mTrack.addView(inflateAction(mimeType, cache, mTrack));
containedTypes.remove(mimeType);
}
}
@@ -801,9 +574,11 @@
if (containedTypes.contains(ClearDefaultsAction.PSEUDO_MIME_TYPE)) {
final ClearDefaultsAction action = (ClearDefaultsAction) mActions.get(
ClearDefaultsAction.PSEUDO_MIME_TYPE).get(0);
- final CheckableImageView view = obtainView();
+ final CheckableImageView view = (CheckableImageView) getLayoutInflater().inflate(
+ R.layout.quickcontact_item, mTrack, false);
+
view.setChecked(false);
- final String description = mContext.getResources().getString(
+ final String description = context.getResources().getString(
R.string.quickcontact_clear_defaults_description);
view.setContentDescription(description);
view.setImageResource(R.drawable.ic_menu_settings_holo_light);
@@ -819,12 +594,13 @@
if (remainingTypes.length > 0) hasData = true;
Arrays.sort(remainingTypes);
for (String mimeType : remainingTypes) {
- mTrack.addView(inflateAction(mimeType, cache), index++);
+ mTrack.addView(inflateAction(mimeType, cache, mTrack), index++);
}
if (!hasData) {
// When there is no data to display, add a TextView to show the user there's no data
- View view = mInflater.inflate(R.layout.quickcontact_item_nodata, mTrack, false);
+ View view = getLayoutInflater().inflate(
+ R.layout.quickcontact_item_nodata, mTrack, false);
mTrack.addView(view, index++);
}
}
@@ -833,7 +609,9 @@
* Clears the defaults currently set on the Contact
*/
private void clearDefaults() {
+ final Context context = this;
final Set<String> mimeTypesKeySet = mDefaultsMap.keySet();
+
// Copy to array so that we can modify the HashMap below
final String[] mimeTypes = new String[mimeTypesKeySet.size()];
mimeTypesKeySet.toArray(mimeTypes);
@@ -841,9 +619,9 @@
// Send clear default Intents, one by one
for (String mimeType : mimeTypes) {
final Action action = mDefaultsMap.get(mimeType);
- final Intent intent =
- ContactSaveService.createClearPrimaryIntent(mContext, action.getDataId());
- mContext.startService(intent);
+ final Intent intent = ContactSaveService.createClearPrimaryIntent(
+ context, action.getDataId());
+ context.startService(intent);
mDefaultsMap.remove(mimeType);
}
@@ -854,7 +632,6 @@
for (int i = mTrack.getChildCount() - 1; i >= 0; i--) {
final CheckableImageView button = (CheckableImageView) mTrack.getChildAt(i);
if (button.getTag() instanceof ClearDefaultsAction) {
- releaseView(button);
mTrack.removeViewAt(i);
break;
}
@@ -878,41 +655,15 @@
}
/**
- * 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(CheckableImageView)} to return back into the pool for
- * later recycling.
- */
- private synchronized CheckableImageView obtainView() {
- CheckableImageView view = mActionPool.poll();
- if (view == null || QuickContactActivity.FORCE_CREATE) {
- view = (CheckableImageView) 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(CheckableImageView view) {
- mActionPool.offer(view);
- mActionRecycled++;
- }
-
- /**
* Inflate the in-track view for the action of the given MIME-type, collapsing duplicate values.
* Will use the icon provided by the {@link DataKind}.
*/
- private View inflateAction(String mimeType, ResolveCache resolveCache) {
- final CheckableImageView view = obtainView();
+ private View inflateAction(String mimeType, ResolveCache resolveCache, ViewGroup root) {
+ final CheckableImageView view = (CheckableImageView) getLayoutInflater().inflate(
+ R.layout.quickcontact_item, root, false);
// Add direct intent if single child, otherwise flag for multiple
List<Action> children = mActions.get(mimeType);
- if (children.size() > 1) {
- Collapser.collapseList(children);
- }
view.setTag(mimeType);
final Action firstInfo = children.get(0);
@@ -989,6 +740,13 @@
expandAnimator.setDuration(ANIMATION_EXPAND_TIME);
expandAnimator.start();
+ expandAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mBackground.clearBottomOverride();
+ }
+ });
+
final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(mFooter,
"alpha", 0.0f, 1.0f);
fadeInAnimator.setDuration(ANIMATION_FADE_IN_TIME);
@@ -1001,9 +759,12 @@
/** {@inheritDoc} */
@Override
public void onClick(View view) {
+ final Context context = this;
+
final boolean isActionView = (view instanceof CheckableImageView);
final CheckableImageView actionView = isActionView ? (CheckableImageView)view : null;
final Object tag = view.getTag();
+
if (tag instanceof ClearDefaultsAction) {
// Do nothing if already open
if (actionView == mLastAction) return;
@@ -1044,29 +805,28 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final View result = convertView != null ? convertView :
- mInflater.inflate(R.layout.quickcontact_default_item,
- parent, false);
+ if (convertView == null) {
+ convertView = getLayoutInflater().inflate(
+ R.layout.quickcontact_default_item, parent, false);
+ }
+
// Set action title based on summary value
final Action defaultAction = actions[position];
- TextView text1 = (TextView)result.findViewById(android.R.id.text1);
- TextView text2 = (TextView)result.findViewById(android.R.id.text2);
+ final TextView text1 = (TextView) convertView.findViewById(
+ android.R.id.text1);
+ final TextView text2 = (TextView) convertView.findViewById(
+ android.R.id.text2);
text1.setText(defaultAction.getHeader());
text2.setText(defaultAction.getBody());
- result.setTag(defaultAction);
- return result;
+ convertView.setTag(defaultAction);
+ return convertView;
}
});
animateExpand(true);
- // Make sure we resize to make room for ListView
- if (mDecor != null) {
- mDecor.forceLayout();
- mDecor.invalidate();
- }
}
};
if (mFooter.getVisibility() == View.VISIBLE) {
@@ -1115,24 +875,24 @@
public void run() {
// Incoming tag is concrete intent, so try launching
try {
- mContext.startActivity(action.getIntent());
+ context.startActivity(action.getIntent());
} catch (ActivityNotFoundException e) {
- Toast.makeText(mContext, R.string.quickcontact_missing_app,
+ Toast.makeText(context, R.string.quickcontact_missing_app,
Toast.LENGTH_SHORT).show();
}
// Hide the resolution list, if present
setNewActionViewChecked(null);
- dismiss();
- mFooter.setVisibility(View.GONE);
// Set default?
final long dataId = action.getDataId();
if (makePrimary && dataId != -1) {
Intent serviceIntent = ContactSaveService.createSetSuperPrimaryIntent(
- mContext, dataId);
- mContext.startService(serviceIntent);
+ context, dataId);
+ context.startService(serviceIntent);
}
+
+ hide(false);
}
};
if (isActionView && mFooter.getVisibility() == View.VISIBLE) {
@@ -1177,31 +937,31 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- final View result = convertView != null ? convertView :
- mInflater.inflate(R.layout.quickcontact_resolve_item,
- parent, false);
+ if (convertView == null) {
+ convertView = getLayoutInflater().inflate(
+ R.layout.quickcontact_resolve_item, parent, false);
+ }
+
// Set action title based on summary value
final Action listAction = actionList.get(position);
- TextView text1 = (TextView)result.findViewById(android.R.id.text1);
- TextView text2 = (TextView)result.findViewById(android.R.id.text2);
+ final TextView text1 = (TextView) convertView.findViewById(
+ android.R.id.text1);
+ final TextView text2 = (TextView) convertView.findViewById(
+ android.R.id.text2);
text1.setText(listAction.getHeader());
text2.setText(listAction.getBody());
- result.setTag(listAction);
- return result;
+ convertView.setTag(listAction);
+ return convertView;
}
});
animateExpand(false);
- // Make sure we resize to make room for ListView
- if (mDecor != null) {
- mDecor.forceLayout();
- mDecor.invalidate();
- }
}
};
+
if (mFooter.getVisibility() == View.VISIBLE) {
// If the expansion list is currently opened, animate its collapse and then
// execute the target app
@@ -1212,191 +972,6 @@
}
}
- @Override
- public void onBackPressed() {
- dismiss();
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- if (mWindow.superDispatchKeyEvent(event)) {
- return true;
- }
- return event.dispatch(this, mDecor != null
- ? mDecor.getKeyDispatcherState() : null, this);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- event.startTracking();
- return true;
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
- && !event.isCanceled()) {
- onBackPressed();
- return true;
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onKeyLongPress(int keyCode, KeyEvent event) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
- return false;
- }
-
- /** {@inheritDoc} */
- public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- return mWindow.superDispatchKeyShortcutEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- // TODO: make this window accessible
- return false;
- }
-
- /**
- * Detect if the given {@link MotionEvent} is outside the boundaries of this
- * window, which usually means we should dismiss.
- */
- protected void detectEventOutside(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN && mDecor != null) {
- // Only try detecting outside events on down-press
- mDecor.getHitRect(mRect);
- final int x = (int)event.getX();
- final int y = (int)event.getY();
- if (!mRect.contains(x, y)) {
- event.setAction(MotionEvent.ACTION_OUTSIDE);
- }
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- detectEventOutside(event);
- if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
- dismiss();
- return true;
- }
- return mWindow.superDispatchTouchEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchTrackballEvent(MotionEvent event) {
- return mWindow.superDispatchTrackballEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean dispatchGenericMotionEvent(MotionEvent event) {
- return mWindow.superDispatchGenericMotionEvent(event);
- }
-
- /** {@inheritDoc} */
- @Override
- public void onContentChanged() {
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public View onCreatePanelView(int featureId) {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public void onPanelClosed(int featureId, Menu menu) {
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean onSearchRequested() {
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public void onWindowAttributesChanged(android.view.WindowManager.LayoutParams attrs) {
- if (mDecor != null) {
- mWindowManager.updateViewLayout(mDecor, attrs);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- }
-
- /** {@inheritDoc} */
- @Override
- public void onAttachedToWindow() {
- // No actions
- }
-
- /** {@inheritDoc} */
- @Override
- public void onDetachedFromWindow() {
- // No actions
- }
-
- /** {@inheritDoc} */
- @Override
- public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
- return null;
- }
-
- @Override
- public void onActionModeStarted(ActionMode mode) {
- }
-
- @Override
- public void onActionModeFinished(ActionMode mode) {
- }
private interface DataQuery {
final String[] PROJECTION = new String[] {
diff --git a/src/com/android/contacts/util/AccountsListAdapter.java b/src/com/android/contacts/util/AccountsListAdapter.java
index 8dbfc8d..97a9f84 100644
--- a/src/com/android/contacts/util/AccountsListAdapter.java
+++ b/src/com/android/contacts/util/AccountsListAdapter.java
@@ -60,7 +60,9 @@
final AccountType accountType = mAccountTypes.getAccountType(account.type);
text1.setText(account.name);
- text2.setText(accountType.getDisplayLabel(mContext));
+ if (text2 != null) {
+ text2.setText(accountType.getDisplayLabel(mContext));
+ }
icon.setImageDrawable(accountType.getDisplayIcon(mContext));
return resultView;
diff --git a/src/com/android/contacts/util/NameConverter.java b/src/com/android/contacts/util/NameConverter.java
new file mode 100644
index 0000000..9853821
--- /dev/null
+++ b/src/com/android/contacts/util/NameConverter.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.util;
+
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.net.Uri.Builder;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.text.TextUtils;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Utility class for converting between a display name and structured name (and vice-versa), via
+ * calls to the contact provider.
+ */
+public class NameConverter {
+
+ /**
+ * The array of fields that comprise a structured name.
+ */
+ public static final String[] STRUCTURED_NAME_FIELDS = new String[] {
+ StructuredName.PREFIX,
+ StructuredName.GIVEN_NAME,
+ StructuredName.MIDDLE_NAME,
+ StructuredName.FAMILY_NAME,
+ StructuredName.SUFFIX
+ };
+
+ /**
+ * Converts the given structured name (provided as a map from {@link StructuredName} fields to
+ * corresponding values) into a display name string.
+ * <p>
+ * Note that this operates via a call back to the ContactProvider, but it does not access the
+ * database, so it should be safe to call from the UI thread. See
+ * ContactsProvider2.completeName() for the underlying method call.
+ * @param context Activity context.
+ * @param structuredName The structured name map to convert.
+ * @return The display name computed from the structured name map.
+ */
+ public static String structuredNameToDisplayName(Context context,
+ Map<String, String> structuredName) {
+ Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
+ for (String key : STRUCTURED_NAME_FIELDS) {
+ if (structuredName.containsKey(key)) {
+ appendQueryParameter(builder, key, structuredName.get(key));
+ }
+ }
+ return fetchDisplayName(context, builder.build());
+ }
+
+ /**
+ * Converts the given structured name (provided as ContentValues) into a display name string.
+ * @param context Activity context.
+ * @param values The content values containing values comprising the structured name.
+ * @return
+ */
+ public static String structuredNameToDisplayName(Context context, ContentValues values) {
+ Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
+ for (String key : STRUCTURED_NAME_FIELDS) {
+ if (values.containsKey(key)) {
+ appendQueryParameter(builder, key, values.getAsString(key));
+ }
+ }
+ return fetchDisplayName(context, builder.build());
+ }
+
+ /**
+ * Helper method for fetching the display name via the given URI.
+ */
+ private static String fetchDisplayName(Context context, Uri uri) {
+ String displayName = null;
+ Cursor cursor = context.getContentResolver().query(uri, new String[]{
+ StructuredName.DISPLAY_NAME,
+ }, null, null, null);
+
+ try {
+ if (cursor.moveToFirst()) {
+ displayName = cursor.getString(0);
+ }
+ } finally {
+ cursor.close();
+ }
+ return displayName;
+ }
+
+ /**
+ * Converts the given display name string into a structured name (as a map from
+ * {@link StructuredName} fields to corresponding values).
+ * <p>
+ * Note that this operates via a call back to the ContactProvider, but it does not access the
+ * database, so it should be safe to call from the UI thread.
+ * @param context Activity context.
+ * @param displayName The display name to convert.
+ * @return The structured name map computed from the display name.
+ */
+ public static Map<String, String> displayNameToStructuredName(Context context,
+ String displayName) {
+ Map<String, String> structuredName = new TreeMap<String, String>();
+ Builder builder = ContactsContract.AUTHORITY_URI.buildUpon().appendPath("complete_name");
+
+ appendQueryParameter(builder, StructuredName.DISPLAY_NAME, displayName);
+ Cursor cursor = context.getContentResolver().query(builder.build(), STRUCTURED_NAME_FIELDS,
+ null, null, null);
+
+ try {
+ if (cursor.moveToFirst()) {
+ for (int i = 0; i < STRUCTURED_NAME_FIELDS.length; i++) {
+ structuredName.put(STRUCTURED_NAME_FIELDS[i], cursor.getString(i));
+ }
+ }
+ } finally {
+ cursor.close();
+ }
+ return structuredName;
+ }
+
+ /**
+ * Converts the given display name string into a structured name (inserting the structured
+ * values into a new or existing ContentValues object).
+ * <p>
+ * Note that this operates via a call back to the ContactProvider, but it does not access the
+ * database, so it should be safe to call from the UI thread.
+ * @param context Activity context.
+ * @param displayName The display name to convert.
+ * @param contentValues The content values object to place the structured name values into. If
+ * null, a new one will be created and returned.
+ * @return The ContentValues object containing the structured name fields derived from the
+ * display name.
+ */
+ public static ContentValues displayNameToStructuredName(Context context, String displayName,
+ ContentValues contentValues) {
+ if (contentValues == null) {
+ contentValues = new ContentValues();
+ }
+ Map<String, String> mapValues = displayNameToStructuredName(context, displayName);
+ for (String key : mapValues.keySet()) {
+ contentValues.put(key, mapValues.get(key));
+ }
+ return contentValues;
+ }
+
+ private static void appendQueryParameter(Builder builder, String field, String value) {
+ if (!TextUtils.isEmpty(value)) {
+ builder.appendQueryParameter(field, value);
+ }
+ }
+}
diff --git a/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java b/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
index 83fae29..c8cfc8d 100644
--- a/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
+++ b/src/com/android/contacts/util/NotifyingAsyncQueryHandler.java
@@ -29,8 +29,6 @@
* <p>
* This pattern can be used to perform background queries without leaking
* {@link Context} objects.
- *
- * @hide pending API council review
*/
public class NotifyingAsyncQueryHandler extends AsyncQueryHandler {
private WeakReference<AsyncQueryListener> mListener;
diff --git a/src/com/android/contacts/util/PhoneCapabilityTester.java b/src/com/android/contacts/util/PhoneCapabilityTester.java
index 23319aa..d3a8060 100644
--- a/src/com/android/contacts/util/PhoneCapabilityTester.java
+++ b/src/com/android/contacts/util/PhoneCapabilityTester.java
@@ -16,6 +16,8 @@
package com.android.contacts.util;
+import com.android.contacts.R;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -79,4 +81,12 @@
Uri.fromParts(Constants.SCHEME_SMSTO, "", null));
return isIntentRegistered(context, intent);
}
+
+ /**
+ * True if we are using two-pane layouts ("tablet mode"), false if we are using single views
+ * ("phone mode")
+ */
+ public static boolean isUsingTwoPanes(Context context) {
+ return context.getResources().getBoolean(R.bool.config_use_two_panes);
+ }
}
diff --git a/src/com/android/contacts/vcard/ExportProcessor.java b/src/com/android/contacts/vcard/ExportProcessor.java
index 67c9c4a..e9697d3 100644
--- a/src/com/android/contacts/vcard/ExportProcessor.java
+++ b/src/com/android/contacts/vcard/ExportProcessor.java
@@ -16,24 +16,28 @@
package com.android.contacts.vcard;
import com.android.contacts.R;
-import com.android.contacts.activities.ContactBrowserActivity;
+import com.android.contacts.activities.PeopleActivity;
import com.android.vcard.VCardComposer;
import com.android.vcard.VCardConfig;
import android.app.Notification;
import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContactsEntity;
import android.text.TextUtils;
import android.util.Log;
-import android.widget.RemoteViews;
+import java.io.BufferedWriter;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
/**
* Class for processing one export request from a user. Dropped after exporting requested Uri(s).
@@ -92,6 +96,7 @@
if (DEBUG) Log.d(LOG_TAG, String.format("vCard export (id: %d) has started.", mJobId));
final ExportRequest request = mExportRequest;
VCardComposer composer = null;
+ Writer writer = null;
boolean successful = false;
try {
if (isCancelled()) {
@@ -129,9 +134,14 @@
// VCardConfig.FLAG_USE_QP_TO_PRIMARY_PROPERTIES);
// composer = new VCardComposer(ExportVCardActivity.this, vcardType, true);
- composer.addHandler(composer.new HandlerForOutputStream(outputStream));
-
- if (!composer.init()) {
+ writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+ final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI.buildUpon()
+ .appendQueryParameter(RawContactsEntity.FOR_EXPORT_ONLY, "1")
+ .build();
+ // TODO: should provide better selection.
+ if (!composer.init(Contacts.CONTENT_URI, new String[] {Contacts._ID},
+ null, null,
+ null, contentUriForRawContactsEntity)) {
final String errorReason = composer.getErrorReason();
Log.e(LOG_TAG, "initialization of vCard composer failed: " + errorReason);
final String translatedErrorReason =
@@ -157,7 +167,9 @@
Log.i(LOG_TAG, "Export request is cancelled during composing vCard");
return;
}
- if (!composer.createOneEntry()) {
+ try {
+ writer.write(composer.createOneEntry());
+ } catch (IOException e) {
final String errorReason = composer.getErrorReason();
Log.e(LOG_TAG, "Failed to read a contact: " + errorReason);
final String translatedErrorReason =
@@ -192,7 +204,13 @@
if (composer != null) {
composer.terminate();
}
-
+ if (writer != null) {
+ try {
+ writer.close();
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "IOException is thrown during close(). Ignored. " + e);
+ }
+ }
mService.handleFinishExportNotification(mJobId, successful);
}
}
@@ -233,7 +251,7 @@
private void doFinishNotification(final String title, final String description) {
if (DEBUG) Log.d(LOG_TAG, "send finish notification: " + title + ", " + description);
- final Intent intent = new Intent(mService, ContactBrowserActivity.class);
+ final Intent intent = new Intent(mService, PeopleActivity.class);
final Notification notification =
VCardService.constructFinishNotification(mService, title, description, intent);
mNotificationManager.notify(mJobId, notification);
diff --git a/src/com/android/contacts/vcard/ImportVCardActivity.java b/src/com/android/contacts/vcard/ImportVCardActivity.java
index b3376e9..17b89c3 100644
--- a/src/com/android/contacts/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/vcard/ImportVCardActivity.java
@@ -21,7 +21,6 @@
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.util.AccountSelectionUtil;
import com.android.vcard.VCardEntryCounter;
-import com.android.vcard.VCardInterpreterCollection;
import com.android.vcard.VCardParser;
import com.android.vcard.VCardParser_V21;
import com.android.vcard.VCardParser_V30;
@@ -399,7 +398,6 @@
final ContentResolver resolver = ImportVCardActivity.this.getContentResolver();
VCardEntryCounter counter = null;
VCardSourceDetector detector = null;
- VCardInterpreterCollection interpreter = null;
int vcardVersion = VCARD_VERSION_V21;
try {
boolean shouldUseV30 = false;
@@ -408,9 +406,9 @@
try {
counter = new VCardEntryCounter();
detector = new VCardSourceDetector();
- interpreter = new VCardInterpreterCollection(
- Arrays.asList(counter, detector));
- mVCardParser.parse(is, interpreter);
+ mVCardParser.addInterpreter(counter);
+ mVCardParser.addInterpreter(detector);
+ mVCardParser.parse(is);
} catch (VCardVersionException e1) {
try {
is.close();
@@ -423,9 +421,9 @@
try {
counter = new VCardEntryCounter();
detector = new VCardSourceDetector();
- interpreter = new VCardInterpreterCollection(
- Arrays.asList(counter, detector));
- mVCardParser.parse(is, interpreter);
+ mVCardParser.addInterpreter(counter);
+ mVCardParser.addInterpreter(detector);
+ mVCardParser.parse(is);
} catch (VCardVersionException e2) {
throw new VCardException("vCard with unspported version.");
}
diff --git a/src/com/android/contacts/widget/TextHighlightingAnimation.java b/src/com/android/contacts/widget/TextHighlightingAnimation.java
index 21bbc63..882dd48 100644
--- a/src/com/android/contacts/widget/TextHighlightingAnimation.java
+++ b/src/com/android/contacts/widget/TextHighlightingAnimation.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.widget;
+import com.android.contacts.format.FormatUtils;
import com.android.internal.R;
import android.database.CharArrayBuffer;
@@ -72,7 +73,7 @@
// TODO figure out a way to avoid string allocation
mString = new String(mText.data, 0, mText.sizeCopied);
- int index = indexOf(baseText, highlightedText);
+ int index = FormatUtils.overlapPoint(baseText, highlightedText);
if (index == 0 || index == -1) {
mDimmingEnabled = false;
@@ -83,42 +84,6 @@
}
}
- /**
- * An implementation of indexOf on CharArrayBuffers that finds the first match of
- * the start of buffer2 in buffer1. For example, indexOf("abcd", "cdef") == 2
- */
- private int indexOf(CharArrayBuffer buffer1, CharArrayBuffer buffer2) {
- char[] string1 = buffer1.data;
- char[] string2 = buffer2.data;
- int count1 = buffer1.sizeCopied;
- int count2 = buffer2.sizeCopied;
-
- // Ignore matching tails of the two buffers
- while (count1 > 0 && count2 > 0 && string1[count1 - 1] == string2[count2 - 1]) {
- count1--;
- count2--;
- }
-
- int size = count2;
- for (int i = 0; i < count1; i++) {
- if (i + size > count1) {
- size = count1 - i;
- }
- int j;
- for (j = 0; j < size; j++) {
- if (string1[i+j] != string2[j]) {
- break;
- }
- }
- if (j == size) {
- return i;
- }
- }
-
- return -1;
- }
-
-
@SuppressWarnings("unchecked")
public <T> T[] getSpans(int start, int end, Class<T> type) {
if (mDimmingEnabled) {
diff --git a/tests/res/values/donottranslate_strings.xml b/tests/res/values/donottranslate_strings.xml
index 8557fd6..bd272c3 100644
--- a/tests/res/values/donottranslate_strings.xml
+++ b/tests/res/values/donottranslate_strings.xml
@@ -32,6 +32,7 @@
<item>ACTION_PICK: phone (legacy)</item>
<item>ACTION_PICK: postal</item>
<item>ACTION_PICK: postal (legacy)</item>
+ <item>ACTION_PICK: e-mail</item>
<item>ACTION_CREATE_SHORTCUT: contact</item>
<item>ACTION_CREATE_SHORTCUT: dial</item>
<item>ACTION_CREATE_SHORTCUT: message</item>
diff --git a/tests/src/com/android/contacts/ContactLoaderTest.java b/tests/src/com/android/contacts/ContactLoaderTest.java
index 503fc64..0e0e2b0 100644
--- a/tests/src/com/android/contacts/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/ContactLoaderTest.java
@@ -29,10 +29,12 @@
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.StatusUpdates;
import android.test.LoaderTestCase;
+import android.test.suitebuilder.annotation.LargeTest;
/**
* Runs ContactLoader tests for the the contact-detail and editor view.
*/
+@LargeTest
public class ContactLoaderTest extends LoaderTestCase {
ContactsMockContext mMockContext;
MockContentProvider mContactsProvider;
@@ -265,7 +267,8 @@
mContactsProvider.expectQuery(baseUri)
.withProjection(new String[] {
Contacts.NAME_RAW_CONTACT_ID, Contacts.DISPLAY_NAME_SOURCE,
- Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME, Contacts.PHONETIC_NAME,
+ Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME,
+ Contacts.DISPLAY_NAME_ALTERNATIVE, Contacts.PHONETIC_NAME,
Contacts.PHOTO_ID, Contacts.STARRED, Contacts.CONTACT_PRESENCE,
Contacts.CONTACT_STATUS, Contacts.CONTACT_STATUS_TIMESTAMP,
Contacts.CONTACT_STATUS_RES_PACKAGE, Contacts.CONTACT_STATUS_LABEL,
@@ -299,7 +302,7 @@
.withSortOrder(Contacts.Entity.RAW_CONTACT_ID)
.returnRow(
rawContactId, 40,
- "aa%12%@!", "John Doe", "jdo",
+ "aa%12%@!", "John Doe", "Doe, John", "jdo",
0, 0, StatusUpdates.AVAILABLE,
"Having lunch", 0,
"mockPkg1", 10,
diff --git a/tests/src/com/android/contacts/DialerLaunchPerformance.java b/tests/src/com/android/contacts/DialerLaunchPerformance.java
index ae78082..0803c6b 100644
--- a/tests/src/com/android/contacts/DialerLaunchPerformance.java
+++ b/tests/src/com/android/contacts/DialerLaunchPerformance.java
@@ -32,7 +32,7 @@
mIntent.setAction(Intent.ACTION_MAIN);
mIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mIntent.setComponent(new ComponentName("com.android.contacts",
- "com.android.contacts.DialtactsActivity"));
+ "com.android.contacts.activities.DialtactsActivity"));
start();
}
diff --git a/tests/src/com/android/contacts/EntityModifierTests.java b/tests/src/com/android/contacts/EntityModifierTests.java
index 4acaa92..63dd84d 100644
--- a/tests/src/com/android/contacts/EntityModifierTests.java
+++ b/tests/src/com/android/contacts/EntityModifierTests.java
@@ -20,23 +20,31 @@
import static android.content.ContentProviderOperation.TYPE_INSERT;
import static android.content.ContentProviderOperation.TYPE_UPDATE;
+import com.google.android.collect.Lists;
+
import com.android.contacts.model.AccountType;
-import com.android.contacts.model.AccountType.DataKind;
import com.android.contacts.model.AccountType.EditType;
import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
import com.android.contacts.model.EntityDelta;
import com.android.contacts.model.EntityDelta.ValuesDelta;
import com.android.contacts.model.EntityDeltaList;
import com.android.contacts.model.EntityModifier;
+import com.android.contacts.model.ExchangeAccountType;
+import com.android.contacts.model.GoogleAccountType;
+import com.android.contacts.tests.mocks.ContactsMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
-import com.google.android.collect.Lists;
+import com.android.contacts.tests.mocks.MockContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
+import android.net.Uri;
import android.os.Bundle;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -81,45 +89,54 @@
MockContactsSource() {
this.accountType = TEST_ACCOUNT_TYPE;
+ final DataKind nameKind = new DataKind(StructuredName.CONTENT_ITEM_TYPE,
+ R.string.nameLabelsGroup, -1, -1, true, -1, -1, -1);
+ nameKind.typeOverallMax = 1;
+ addKind(nameKind);
+
// Phone allows maximum 2 home, 1 work, and unlimited other, with
// constraint of 5 numbers maximum.
- DataKind kind = new DataKind(Phone.CONTENT_ITEM_TYPE, -1, -1, 10, true);
+ final DataKind phoneKind = new DataKind(
+ Phone.CONTENT_ITEM_TYPE, -1, -1, 10, true, -1, -1, -1);
- kind.typeOverallMax = 5;
- kind.typeColumn = Phone.TYPE;
- kind.typeList = Lists.newArrayList();
- kind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2));
- kind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1));
- kind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true));
- kind.typeList.add(new EditType(Phone.TYPE_OTHER, -1));
+ phoneKind.typeOverallMax = 5;
+ phoneKind.typeColumn = Phone.TYPE;
+ phoneKind.typeList = Lists.newArrayList();
+ phoneKind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2));
+ phoneKind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1));
+ phoneKind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true));
+ phoneKind.typeList.add(new EditType(Phone.TYPE_OTHER, -1));
- kind.fieldList = Lists.newArrayList();
- kind.fieldList.add(new EditField(Phone.NUMBER, -1, -1));
- kind.fieldList.add(new EditField(Phone.LABEL, -1, -1));
+ phoneKind.fieldList = Lists.newArrayList();
+ phoneKind.fieldList.add(new EditField(Phone.NUMBER, -1, -1));
+ phoneKind.fieldList.add(new EditField(Phone.LABEL, -1, -1));
- addKind(kind);
+ addKind(phoneKind);
// Email is unlimited
- kind = new DataKind(Email.CONTENT_ITEM_TYPE, -1, -1, 10, true);
- kind.typeOverallMax = -1;
- kind.fieldList = Lists.newArrayList();
- kind.fieldList.add(new EditField(Email.DATA, -1, -1));
- addKind(kind);
+ final DataKind emailKind = new DataKind(
+ Email.CONTENT_ITEM_TYPE, -1, -1, 10, true, -1, -1, -1);
+ emailKind.typeOverallMax = -1;
+ emailKind.fieldList = Lists.newArrayList();
+ emailKind.fieldList.add(new EditField(Email.DATA, -1, -1));
+ addKind(emailKind);
// IM is only one
- kind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, -1, 10, true);
- kind.typeOverallMax = 1;
- kind.fieldList = Lists.newArrayList();
- kind.fieldList.add(new EditField(Im.DATA, -1, -1));
- addKind(kind);
+ final DataKind imKind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, -1, 10,
+ true, -1, -1, -1);
+ imKind.typeOverallMax = 1;
+ imKind.fieldList = Lists.newArrayList();
+ imKind.fieldList.add(new EditField(Im.DATA, -1, -1));
+ addKind(imKind);
// Organization is only one
- kind = new DataKind(Organization.CONTENT_ITEM_TYPE, -1, -1, 10, true);
- kind.typeOverallMax = 1;
- kind.fieldList = Lists.newArrayList();
- kind.fieldList.add(new EditField(Organization.COMPANY, -1, -1));
- kind.fieldList.add(new EditField(Organization.TITLE, -1, -1));
- addKind(kind);
+ final DataKind orgKind = new DataKind(
+ Organization.CONTENT_ITEM_TYPE, -1, -1, 10, true, -1, -1, -1);
+ orgKind.typeOverallMax = 1;
+ orgKind.fieldList = Lists.newArrayList();
+ orgKind.fieldList.add(new EditField(Organization.COMPANY, -1, -1));
+ orgKind.fieldList.add(new EditField(Organization.TITLE, -1, -1));
+ addKind(orgKind);
}
@Override
@@ -330,7 +347,7 @@
// Test row that has type values, but core fields are empty
final EntityDelta state = getEntity(TEST_ID);
- final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
+ EntityModifier.insertChild(state, kindPhone, typeHome);
// Build diff, expecting insert for data row and update enforcement
final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
@@ -420,7 +437,7 @@
public void testTrimEmptyUntouched() {
final AccountType source = getAccountType();
final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
- final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+ EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
// Build "before" that has empty row
final EntityDelta state = getEntity(TEST_ID);
@@ -497,7 +514,7 @@
final AccountType accountType = getAccountType();
final AccountTypeManager accountTypes = getAccountTypes(accountType);
final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
- final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
+ EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
// Try creating a contact without any child entries
final EntityDelta state = getEntity(null);
@@ -528,7 +545,7 @@
// Try creating a contact with single empty entry
final EntityDelta state = getEntity(null);
- final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
+ EntityModifier.insertChild(state, kindPhone, typeHome);
final EntityDeltaList set = EntityDeltaList.fromSingle(state);
// Build diff, expecting two insert operations
@@ -746,4 +763,448 @@
final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size();
assertEquals("Expected to create organization", 1, count);
}
+
+ public void testMigrateWithDisplayNameFromGoogleToExchange1() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
+
+ ContactsMockContext context = new ContactsMockContext(getContext());
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ mockNameValues.put(StructuredName.PREFIX, "prefix");
+ mockNameValues.put(StructuredName.GIVEN_NAME, "given");
+ mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
+ mockNameValues.put(StructuredName.FAMILY_NAME, "family");
+ mockNameValues.put(StructuredName.SUFFIX, "suffix");
+ mockNameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "PHONETIC_FAMILY");
+ mockNameValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "PHONETIC_MIDDLE");
+ mockNameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "PHONETIC_GIVEN");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+ List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
+ assertEquals(1, list.size());
+
+ ContentValues output = list.get(0).getAfter();
+ assertEquals("prefix", output.getAsString(StructuredName.PREFIX));
+ assertEquals("given", output.getAsString(StructuredName.GIVEN_NAME));
+ assertEquals("middle", output.getAsString(StructuredName.MIDDLE_NAME));
+ assertEquals("family", output.getAsString(StructuredName.FAMILY_NAME));
+ assertEquals("suffix", output.getAsString(StructuredName.SUFFIX));
+ // Phonetic middle name isn't supported by Exchange.
+ assertEquals("PHONETIC_FAMILY", output.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
+ assertEquals("PHONETIC_GIVEN", output.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
+ }
+
+ public void testMigrateWithDisplayNameFromGoogleToExchange2() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
+
+ ContactsMockContext context = new ContactsMockContext(getContext());
+ MockContentProvider provider = context.getContactsProvider();
+
+ String inputDisplayName = "prefix given middle family suffix";
+ // The method will ask the provider to split/join StructuredName.
+ Uri uriForBuildDisplayName =
+ ContactsContract.AUTHORITY_URI
+ .buildUpon()
+ .appendPath("complete_name")
+ .appendQueryParameter(StructuredName.DISPLAY_NAME, inputDisplayName)
+ .build();
+ provider.expectQuery(uriForBuildDisplayName)
+ .returnRow("prefix", "given", "middle", "family", "suffix")
+ .withProjection(StructuredName.PREFIX, StructuredName.GIVEN_NAME,
+ StructuredName.MIDDLE_NAME, StructuredName.FAMILY_NAME,
+ StructuredName.SUFFIX);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ mockNameValues.put(StructuredName.DISPLAY_NAME, inputDisplayName);
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+ List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
+ assertEquals(1, list.size());
+
+ ContentValues outputValues = list.get(0).getAfter();
+ assertEquals("prefix", outputValues.getAsString(StructuredName.PREFIX));
+ assertEquals("given", outputValues.getAsString(StructuredName.GIVEN_NAME));
+ assertEquals("middle", outputValues.getAsString(StructuredName.MIDDLE_NAME));
+ assertEquals("family", outputValues.getAsString(StructuredName.FAMILY_NAME));
+ assertEquals("suffix", outputValues.getAsString(StructuredName.SUFFIX));
+ }
+
+ public void testMigrateWithStructuredNameFromExchangeToGoogle() {
+ AccountType oldAccountType = new ExchangeAccountType(getContext(), "");
+ AccountType newAccountType = new GoogleAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
+
+ ContactsMockContext context = new ContactsMockContext(getContext());
+ MockContentProvider provider = context.getContactsProvider();
+
+ // The method will ask the provider to split/join StructuredName.
+ Uri uriForBuildDisplayName =
+ ContactsContract.AUTHORITY_URI
+ .buildUpon()
+ .appendPath("complete_name")
+ .appendQueryParameter(StructuredName.PREFIX, "prefix")
+ .appendQueryParameter(StructuredName.GIVEN_NAME, "given")
+ .appendQueryParameter(StructuredName.MIDDLE_NAME, "middle")
+ .appendQueryParameter(StructuredName.FAMILY_NAME, "family")
+ .appendQueryParameter(StructuredName.SUFFIX, "suffix")
+ .build();
+ provider.expectQuery(uriForBuildDisplayName)
+ .returnRow("prefix given middle family suffix")
+ .withProjection(StructuredName.DISPLAY_NAME);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ mockNameValues.put(StructuredName.PREFIX, "prefix");
+ mockNameValues.put(StructuredName.GIVEN_NAME, "given");
+ mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
+ mockNameValues.put(StructuredName.FAMILY_NAME, "family");
+ mockNameValues.put(StructuredName.SUFFIX, "suffix");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateStructuredName(context, oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size());
+ ContentValues outputValues = list.get(0).getAfter();
+ assertEquals("prefix given middle family suffix",
+ outputValues.getAsString(StructuredName.DISPLAY_NAME));
+ }
+
+ public void testMigratePostalFromGoogleToExchange() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
+ mockNameValues.put(StructuredPostal.FORMATTED_ADDRESS, "formatted_address");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migratePostal(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size());
+ ContentValues outputValues = list.get(0).getAfter();
+ // FORMATTED_ADDRESS isn't supported by Exchange.
+ assertNull(outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS));
+ assertEquals("formatted_address", outputValues.getAsString(StructuredPostal.STREET));
+ }
+
+ public void testMigratePostalFromExchangeToGoogle() {
+ AccountType oldAccountType = new ExchangeAccountType(getContext(), "");
+ AccountType newAccountType = new GoogleAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
+ mockNameValues.put(StructuredPostal.COUNTRY, "country");
+ mockNameValues.put(StructuredPostal.POSTCODE, "postcode");
+ mockNameValues.put(StructuredPostal.REGION, "region");
+ mockNameValues.put(StructuredPostal.CITY, "city");
+ mockNameValues.put(StructuredPostal.STREET, "street");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migratePostal(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size());
+ ContentValues outputValues = list.get(0).getAfter();
+
+ // Check FORMATTED_ADDRESS contains all info.
+ String formattedAddress = outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
+ assertNotNull(formattedAddress);
+ assertTrue(formattedAddress.contains("country"));
+ assertTrue(formattedAddress.contains("postcode"));
+ assertTrue(formattedAddress.contains("region"));
+ assertTrue(formattedAddress.contains("postcode"));
+ assertTrue(formattedAddress.contains("city"));
+ assertTrue(formattedAddress.contains("street"));
+ }
+
+ public void testMigrateEventFromGoogleToExchange1() {
+ testMigrateEventCommon(new GoogleAccountType(getContext(), ""),
+ new ExchangeAccountType(getContext(), ""));
+ }
+
+ public void testMigrateEventFromExchangeToGoogle() {
+ testMigrateEventCommon(new ExchangeAccountType(getContext(), ""),
+ new GoogleAccountType(getContext(), ""));
+ }
+
+ private void testMigrateEventCommon(AccountType oldAccountType, AccountType newAccountType) {
+ DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Event.START_DATE, "1972-02-08");
+ mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateEvent(oldState, newState, kind, 1990);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size()); // Anniversary should be dropped.
+ ContentValues outputValues = list.get(0).getAfter();
+
+ assertEquals("1972-02-08", outputValues.getAsString(Event.START_DATE));
+ assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
+ }
+
+ public void testMigrateEventFromGoogleToExchange2() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
+ // No year format is not supported by Exchange.
+ mockNameValues.put(Event.START_DATE, "--06-01");
+ mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Event.START_DATE, "1980-08-02");
+ // Anniversary is not supported by Exchange
+ mockNameValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateEvent(oldState, newState, kind, 1990);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size()); // Anniversary should be dropped.
+ ContentValues outputValues = list.get(0).getAfter();
+
+ // Default year should be used.
+ assertEquals("1990-06-01", outputValues.getAsString(Event.START_DATE));
+ assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
+ }
+
+ public void testMigrateEmailFromGoogleToExchange() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Email.TYPE, Email.TYPE_CUSTOM);
+ mockNameValues.put(Email.LABEL, "custom_type");
+ mockNameValues.put(Email.ADDRESS, "address1");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Email.TYPE, Email.TYPE_HOME);
+ mockNameValues.put(Email.ADDRESS, "address2");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Email.TYPE, Email.TYPE_WORK);
+ mockNameValues.put(Email.ADDRESS, "address3");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ // Exchange can have up to 3 email entries. This 4th entry should be dropped.
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Email.TYPE, Email.TYPE_OTHER);
+ mockNameValues.put(Email.ADDRESS, "address4");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Email.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(3, list.size());
+
+ ContentValues outputValues = list.get(0).getAfter();
+ assertEquals(Email.TYPE_CUSTOM, outputValues.getAsInteger(Email.TYPE).intValue());
+ assertEquals("custom_type", outputValues.getAsString(Email.LABEL));
+ assertEquals("address1", outputValues.getAsString(Email.ADDRESS));
+
+ outputValues = list.get(1).getAfter();
+ assertEquals(Email.TYPE_HOME, outputValues.getAsInteger(Email.TYPE).intValue());
+ assertEquals("address2", outputValues.getAsString(Email.ADDRESS));
+
+ outputValues = list.get(2).getAfter();
+ assertEquals(Email.TYPE_WORK, outputValues.getAsInteger(Email.TYPE).intValue());
+ assertEquals("address3", outputValues.getAsString(Email.ADDRESS));
+ }
+
+ public void testMigrateImFromGoogleToExchange() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
+ // Exchange doesn't support TYPE_HOME
+ mockNameValues.put(Im.TYPE, Im.TYPE_HOME);
+ mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER);
+ mockNameValues.put(Im.DATA, "im1");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
+ // Exchange doesn't support TYPE_WORK
+ mockNameValues.put(Im.TYPE, Im.TYPE_WORK);
+ mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO);
+ mockNameValues.put(Im.DATA, "im2");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
+ mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM);
+ mockNameValues.put(Im.CUSTOM_PROTOCOL, "custom_protocol");
+ mockNameValues.put(Im.DATA, "im3");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ // Exchange can have up to 3 IM entries. This 4th entry should be dropped.
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
+ mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
+ mockNameValues.put(Im.DATA, "im4");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Im.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(3, list.size());
+
+ assertNotNull(kind.defaultValues.getAsInteger(Im.TYPE));
+
+ int defaultType = kind.defaultValues.getAsInteger(Im.TYPE);
+
+ ContentValues outputValues = list.get(0).getAfter();
+ // HOME should become default type.
+ assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
+ assertEquals(Im.PROTOCOL_JABBER, outputValues.getAsInteger(Im.PROTOCOL).intValue());
+ assertEquals("im1", outputValues.getAsString(Im.DATA));
+
+ outputValues = list.get(1).getAfter();
+ assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
+ assertEquals(Im.PROTOCOL_YAHOO, outputValues.getAsInteger(Im.PROTOCOL).intValue());
+ assertEquals("im2", outputValues.getAsString(Im.DATA));
+
+ outputValues = list.get(2).getAfter();
+ assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
+ assertEquals(Im.PROTOCOL_CUSTOM, outputValues.getAsInteger(Im.PROTOCOL).intValue());
+ assertEquals("custom_protocol", outputValues.getAsString(Im.CUSTOM_PROTOCOL));
+ assertEquals("im3", outputValues.getAsString(Im.DATA));
+ }
+
+ public void testMigratePhoneFromGoogleToExchange() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Phone.TYPE, Phone.TYPE_HOME);
+ mockNameValues.put(Phone.NUMBER, "1");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Phone.TYPE, Phone.TYPE_MOBILE);
+ mockNameValues.put(Phone.NUMBER, "2");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ // Exchange doesn't support this type. Default to HOME
+ mockNameValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
+ mockNameValues.put(Phone.LABEL, "custom_type");
+ mockNameValues.put(Phone.NUMBER, "3");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK);
+ mockNameValues.put(Phone.NUMBER, "4");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+ mockNameValues = new ContentValues();
+
+ // This field should be ignored, as Exchange only allows 2 HOME phone numbers while we
+ // already have that number of HOME phones.
+ mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
+ mockNameValues.put(Phone.NUMBER, "5");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(4, list.size());
+
+ int defaultType = kind.typeList.get(0).rawValue;
+
+ ContentValues outputValues = list.get(0).getAfter();
+ assertEquals(Phone.TYPE_HOME, outputValues.getAsInteger(Phone.TYPE).intValue());
+ assertEquals("1", outputValues.getAsString(Phone.NUMBER));
+ outputValues = list.get(1).getAfter();
+ assertEquals(Phone.TYPE_MOBILE, outputValues.getAsInteger(Phone.TYPE).intValue());
+ assertEquals("2", outputValues.getAsString(Phone.NUMBER));
+ outputValues = list.get(2).getAfter();
+ assertEquals(defaultType, outputValues.getAsInteger(Phone.TYPE).intValue());
+ assertNull(outputValues.getAsInteger(Phone.LABEL));
+ assertEquals("3", outputValues.getAsString(Phone.NUMBER));
+ outputValues = list.get(3).getAfter();
+ assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue());
+ assertEquals("4", outputValues.getAsString(Phone.NUMBER));
+ }
+
+ public void testMigrateOrganizationFromGoogleToExchange() {
+ AccountType oldAccountType = new GoogleAccountType(getContext(), "");
+ AccountType newAccountType = new ExchangeAccountType(getContext(), "");
+ DataKind kind = newAccountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
+
+ EntityDelta oldState = new EntityDelta();
+ ContentValues mockNameValues = new ContentValues();
+ mockNameValues.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
+ mockNameValues.put(Organization.COMPANY, "company1");
+ mockNameValues.put(Organization.DEPARTMENT, "department1");
+ oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
+
+ EntityDelta newState = new EntityDelta();
+ EntityModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind);
+
+ List<ValuesDelta> list = newState.getMimeEntries(Organization.CONTENT_ITEM_TYPE);
+ assertNotNull(list);
+ assertEquals(1, list.size());
+
+ ContentValues outputValues = list.get(0).getAfter();
+ assertEquals("company1", outputValues.getAsString(Organization.COMPANY));
+ assertEquals("department1", outputValues.getAsString(Organization.DEPARTMENT));
+ }
}
diff --git a/tests/src/com/android/contacts/RecentCallsListActivityTests.java b/tests/src/com/android/contacts/RecentCallsListActivityTests.java
deleted file mode 100644
index 3c2a9fe..0000000
--- a/tests/src/com/android/contacts/RecentCallsListActivityTests.java
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.contacts;
-
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.provider.CallLog.Calls;
-import android.test.ActivityInstrumentationTestCase2;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
-import android.view.View;
-import android.widget.FrameLayout;
-import com.android.contacts.RecentCallsListActivity;
-import com.android.internal.telephony.CallerInfo;
-import java.util.Date;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Random;
-
-/**
- * Tests for the contact call list activity.
- *
- * Running all tests:
- *
- * runtest contacts
- * or
- * adb shell am instrument \
- * -w com.android.contacts.tests/android.test.InstrumentationTestRunner
- */
-
-public class RecentCallsListActivityTests
- extends ActivityInstrumentationTestCase2<RecentCallsListActivity> {
- static private final String TAG = "RecentCallsListActivityTests";
- static private final String[] CALL_LOG_PROJECTION = new String[] {
- Calls._ID,
- Calls.NUMBER,
- Calls.DATE,
- Calls.DURATION,
- Calls.TYPE,
- Calls.CACHED_NAME,
- Calls.CACHED_NUMBER_TYPE,
- Calls.CACHED_NUMBER_LABEL,
- Calls.COUNTRY_ISO,
- };
- static private final int RAND_DURATION = -1;
- static private final long NOW = -1L;
-
- // We get the call list activity and assign is a frame to build
- // its list. mAdapter is an inner class of
- // RecentCallsListActivity to build the rows (view) in the call
- // list. We reuse it with our own in-mem DB.
- private RecentCallsListActivity mActivity;
- private FrameLayout mParentView;
- private RecentCallsListActivity.RecentCallsAdapter mAdapter;
- private String mVoicemail;
-
- // In memory array to hold the rows corresponding to the 'calls' table.
- private MatrixCursor mCursor;
- private int mIndex; // Of the next row.
-
- private Random mRnd;
-
- // References to the icons bitmaps used to build the list are stored in a
- // map mIcons. The keys to retrieve the icons are:
- // Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE and Calls.MISSED_TYPE.
- private HashMap<Integer, Bitmap> mCallTypeIcons;
-
- // An item in the call list. All the methods performing checks use it.
- private RecentCallsListActivity.RecentCallsListItemViews mItem;
- // The list of views representing the data in the DB. View are in
- // reverse order compare to the DB.
- private View[] mList;
-
- public RecentCallsListActivityTests() {
- super("com.android.contacts", RecentCallsListActivity.class);
- mIndex = 1;
- mRnd = new Random();
- }
-
- @Override
- public void setUp() {
- mActivity = getActivity();
- mVoicemail = mActivity.mVoiceMailNumber;
- mAdapter = mActivity.mAdapter;
- mParentView = new FrameLayout(mActivity);
- mCursor = new MatrixCursor(CALL_LOG_PROJECTION);
- buildIconMap();
- }
-
- /**
- * Checks that the call icon is not visible for private and
- * unknown numbers.
- * Use 2 passes, one where new views are created and one where
- * half of the total views are updated and the other half created.
- */
- @MediumTest
- public void testCallViewIsNotVisibleForPrivateAndUnknownNumbers() {
- final int SIZE = 100;
- mList = new View[SIZE];
-
- // Insert the first batch of entries.
- mCursor.moveToFirst();
- insertRandomEntries(SIZE / 2);
- int startOfSecondBatch = mCursor.getPosition();
-
- buildViewListFromDb();
- checkCallStatus();
-
- // Append the rest of the entries. We keep the first set of
- // views around so they get updated and not built from
- // scratch, this exposes some bugs that are not there when the
- // call log is launched for the 1st time but show up when the
- // call log gets updated afterwards.
- mCursor.move(startOfSecondBatch);
- insertRandomEntries(SIZE / 2);
-
- buildViewListFromDb();
- checkCallStatus();
- }
-
- //
- // HELPERS to check conditions on the DB/views
- //
- /**
- * Check the date of the current list item.
- * @param date That should be present in the call log list
- * item. Only NOW is supported.
- */
- private void checkDate(long date) {
- if (NOW == date) {
- assertEquals("0 mins ago", mItem.dateView.getText());
- }
- throw new UnsupportedOperationException();
- }
-
- /**
- * Checks the right icon is used to represent the call type
- * (missed, incoming, outgoing.) in the current item.
- */
- private void checkCallType(int type) {
- Bitmap icon = ((BitmapDrawable) mItem.iconView.getDrawable()).getBitmap();
- assertEquals(mCallTypeIcons.get(type), icon);
- }
-
- /**
- * Go over all the views in the list and check that the Call
- * icon's visibility matches the nature of the number.
- */
- private void checkCallStatus() {
- for (int i = 0; i < mList.length; i++) {
- if (null == mList[i]) {
- break;
- }
- mItem = (RecentCallsListActivity.RecentCallsListItemViews) mList[i].getTag();
-
- // callView tag is the phone number.
- String number = (String) mItem.callView.getTag();
-
- if (CallerInfo.PRIVATE_NUMBER.equals(number) ||
- CallerInfo.UNKNOWN_NUMBER.equals(number)) {
- assertFalse(View.VISIBLE == mItem.callView.getVisibility());
- } else {
- assertEquals(View.VISIBLE, mItem.callView.getVisibility());
- }
- }
- }
-
-
- //
- // HELPERS to setup the tests.
- //
-
- /**
- * Get the Bitmap from the icons in the contacts package.
- */
- private Bitmap getBitmap(String resName) {
- Resources r = mActivity.getResources();
- int resid = r.getIdentifier(resName, "drawable", "com.android.contacts");
- BitmapDrawable d = (BitmapDrawable) r.getDrawable(resid);
- assertNotNull(d);
- return d.getBitmap();
- }
-
- /**
- * Fetch all the icons we need in tests from the contacts app and store them in a map.
- */
- private void buildIconMap() {
- mCallTypeIcons = new HashMap<Integer, Bitmap>(3);
-
- mCallTypeIcons.put(Calls.INCOMING_TYPE, getBitmap("ic_call_log_list_incoming_call"));
- mCallTypeIcons.put(Calls.MISSED_TYPE, getBitmap("ic_call_log_list_missed_call"));
- mCallTypeIcons.put(Calls.OUTGOING_TYPE, getBitmap("ic_call_log_list_outgoing_call"));
- }
-
- //
- // HELPERS to build/update the call entries (views) from the DB.
- //
-
- /**
- * Read the DB and foreach call either update the existing view if
- * one exists already otherwise create one.
- * The list is build from a DESC view of the DB (last inserted entry is first).
- */
- private void buildViewListFromDb() {
- int i = 0;
- mCursor.moveToLast();
- while(!mCursor.isBeforeFirst()) {
- if (null == mList[i]) {
- mList[i] = mAdapter.newStandAloneView(mActivity, mParentView);
- }
- mAdapter.bindStandAloneView(mList[i], mActivity, mCursor);
- mCursor.moveToPrevious();
- i++;
- }
- }
-
- //
- // HELPERS to insert numbers in the call log DB.
- //
-
- /**
- * Insert a certain number of random numbers in the DB. Makes sure
- * there is at least one private and one unknown number in the DB.
- * @param num Of entries to be inserted.
- */
- private void insertRandomEntries(int num) {
- if (num < 10) {
- throw new IllegalArgumentException("num should be >= 10");
- }
- boolean privateOrUnknownOrVm[];
- privateOrUnknownOrVm = insertRandomRange(0, num - 2);
-
- if (privateOrUnknownOrVm[0] && privateOrUnknownOrVm[1]) {
- insertRandomRange(num - 2, num);
- } else {
- insertPrivate(NOW, RAND_DURATION);
- insertUnknown(NOW, RAND_DURATION);
- }
- }
-
- /**
- * Insert a new call entry in the test DB.
- * @param number The phone number. For unknown and private numbers,
- * use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
- * @param date In millisec since epoch. Use NOW to use the current time.
- * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
- * @param type Eigher Call.OUTGOING_TYPE or Call.INCOMING_TYPE or Call.MISSED_TYPE.
- */
- private void insert(String number, long date, int duration, int type) {
- MatrixCursor.RowBuilder row = mCursor.newRow();
- row.add(mIndex);
- mIndex ++;
- row.add(number);
- if (NOW == date) {
- row.add(new Date().getTime());
- }
- if (duration < 0) {
- duration = mRnd.nextInt(10 * 60); // 0 - 10 minutes random.
- }
- row.add(duration); // duration
- if (mVoicemail != null && mVoicemail.equals(number)) {
- assertEquals(Calls.OUTGOING_TYPE, type);
- }
- row.add(type); // type
- row.add(""); // cached name
- row.add(0); // cached number type
- row.add(""); // cached number label
- row.add("US"); // country ISO
- }
-
- /**
- * Insert a new private call entry in the test DB.
- * @param date In millisec since epoch. Use NOW to use the current time.
- * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
- */
- private void insertPrivate(long date, int duration) {
- insert(CallerInfo.PRIVATE_NUMBER, date, duration, Calls.INCOMING_TYPE);
- }
-
- /**
- * Insert a new unknown call entry in the test DB.
- * @param date In millisec since epoch. Use NOW to use the current time.
- * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
- */
- private void insertUnknown(long date, int duration) {
- insert(CallerInfo.UNKNOWN_NUMBER, date, duration, Calls.INCOMING_TYPE);
- }
-
- /**
- * Insert a new voicemail call entry in the test DB.
- * @param date In millisec since epoch. Use NOW to use the current time.
- * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
- */
- private void insertVoicemail(long date, int duration) {
- // mVoicemail may be null
- if (mVoicemail != null) {
- insert(mVoicemail, date, duration, Calls.OUTGOING_TYPE);
- }
- }
-
- /**
- * Insert a range [start, end) of random numbers in the DB. For
- * each row, there is a 1/10 probability that the number will be
- * marked as PRIVATE or UNKNOWN or VOICEMAIL. For regular numbers, a number is
- * inserted, its last 4 digits will be the number of the iteration
- * in the range.
- * @param start Of the range.
- * @param end Of the range (excluded).
- * @return An array with 2 booleans [0 = private number, 1 =
- * unknown number, 2 = voicemail] to indicate if at least one
- * private or unknown or voicemail number has been inserted. Since
- * the numbers are random some tests may want to enforce the
- * insertion of such numbers.
- */
- // TODO: Should insert numbers with contact entries too.
- private boolean[] insertRandomRange(int start, int end) {
- boolean[] privateOrUnknownOrVm = new boolean[] {false, false, false};
-
- for (int i = start; i < end; i++ ) {
- int type = mRnd.nextInt(10);
-
- if (0 == type) {
- insertPrivate(NOW, RAND_DURATION);
- privateOrUnknownOrVm[0] = true;
- } else if (1 == type) {
- insertUnknown(NOW, RAND_DURATION);
- privateOrUnknownOrVm[1] = true;
- } else if (2 == type) {
- insertVoicemail(NOW, RAND_DURATION);
- privateOrUnknownOrVm[2] = true;
- } else {
- int inout = mRnd.nextBoolean() ? Calls.OUTGOING_TYPE : Calls.INCOMING_TYPE;
- String number = new Formatter().format("1800123%04d", i).toString();
- insert(number, NOW, RAND_DURATION, inout);
- }
- }
- return privateOrUnknownOrVm;
- }
-}
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
new file mode 100644
index 0000000..1dbd56f
--- /dev/null
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -0,0 +1,552 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.activities;
+
+import com.android.contacts.R;
+import com.android.contacts.calllog.CallLogFragment;
+import com.android.contacts.calllog.CallLogFragment.CallLogListItemViews;
+import com.android.internal.telephony.CallerInfo;
+
+import android.content.res.Resources;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.provider.CallLog.Calls;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.Date;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Random;
+
+/**
+ * Tests for the contact call list activity.
+ *
+ * Running all tests:
+ *
+ * runtest contacts
+ * or
+ * adb shell am instrument \
+ * -w com.android.contacts.tests/android.test.InstrumentationTestRunner
+ */
+@LargeTest
+public class CallLogActivityTests
+ extends ActivityInstrumentationTestCase2<CallLogActivity> {
+ static private final String TAG = "CallLogActivityTests";
+ static private final String[] CALL_LOG_PROJECTION = new String[] {
+ Calls._ID,
+ Calls.NUMBER,
+ Calls.DATE,
+ Calls.DURATION,
+ Calls.TYPE,
+ Calls.CACHED_NAME,
+ Calls.CACHED_NUMBER_TYPE,
+ Calls.CACHED_NUMBER_LABEL,
+ Calls.COUNTRY_ISO,
+ };
+ static private final int RAND_DURATION = -1;
+ static private final long NOW = -1L;
+
+ /** A phone number to be used in tests. */
+ private static final String TEST_PHONE_NUMBER = "12125551000";
+ /** The formatted version of {@link #TEST_PHONE_NUMBER}. */
+ private static final String TEST_FORMATTED_PHONE_NUMBER = "1 212-555-1000";
+
+ // We get the call list activity and assign is a frame to build
+ // its list. mAdapter is an inner class of
+ // CallLogActivity to build the rows (view) in the call
+ // list. We reuse it with our own in-mem DB.
+ private CallLogActivity mActivity;
+ private CallLogFragment mFragment;
+ private FrameLayout mParentView;
+ private CallLogFragment.CallLogAdapter mAdapter;
+ private String mVoicemail;
+
+ // In memory array to hold the rows corresponding to the 'calls' table.
+ private MatrixCursor mCursor;
+ private int mIndex; // Of the next row.
+
+ private Random mRnd;
+
+ // References to the icons bitmaps used to build the list are stored in a
+ // map mIcons. The keys to retrieve the icons are:
+ // Calls.INCOMING_TYPE, Calls.OUTGOING_TYPE and Calls.MISSED_TYPE.
+ private HashMap<Integer, Bitmap> mCallTypeIcons;
+
+ // An item in the call list. All the methods performing checks use it.
+ private CallLogFragment.CallLogListItemViews mItem;
+ // The list of views representing the data in the DB. View are in
+ // reverse order compare to the DB.
+ private View[] mList;
+
+ public CallLogActivityTests() {
+ super("com.android.contacts", CallLogActivity.class);
+ mIndex = 1;
+ mRnd = new Random();
+ }
+
+ @Override
+ public void setUp() {
+ mActivity = getActivity();
+ mFragment = mActivity.getFragment();
+ mVoicemail = mFragment.getVoiceMailNumber();
+ mAdapter = mFragment.getAdapter();
+ mParentView = new FrameLayout(mActivity);
+ mCursor = new MatrixCursor(CALL_LOG_PROJECTION);
+ buildIconMap();
+ }
+
+ /**
+ * Checks that the call icon is not visible for private and
+ * unknown numbers.
+ * Use 2 passes, one where new views are created and one where
+ * half of the total views are updated and the other half created.
+ */
+ @MediumTest
+ public void testCallViewIsNotVisibleForPrivateAndUnknownNumbers() {
+ final int SIZE = 100;
+ mList = new View[SIZE];
+
+ // Insert the first batch of entries.
+ mCursor.moveToFirst();
+ insertRandomEntries(SIZE / 2);
+ int startOfSecondBatch = mCursor.getPosition();
+
+ buildViewListFromDb();
+ checkCallStatus();
+
+ // Append the rest of the entries. We keep the first set of
+ // views around so they get updated and not built from
+ // scratch, this exposes some bugs that are not there when the
+ // call log is launched for the 1st time but show up when the
+ // call log gets updated afterwards.
+ mCursor.move(startOfSecondBatch);
+ insertRandomEntries(SIZE / 2);
+
+ buildViewListFromDb();
+ checkCallStatus();
+ }
+
+ @MediumTest
+ public void testCallAndGroupViews_GroupView() {
+ mCursor.moveToFirst();
+ insert(CallerInfo.PRIVATE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ insert(CallerInfo.PRIVATE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ insert(CallerInfo.PRIVATE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ View view = mAdapter.newGroupView(getActivity(), mParentView);
+ mAdapter.bindGroupView(view, getActivity(), mCursor, 3, false);
+ assertNull(view.findViewById(R.id.call_icon));
+ assertNotNull(view.findViewById(R.id.groupIndicator));
+ }
+
+ @MediumTest
+ public void testCallAndGroupViews_StandAloneView() {
+ mCursor.moveToFirst();
+ insert(CallerInfo.PRIVATE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+ assertNotNull(view.findViewById(R.id.call_icon));
+ assertNull(view.findViewById(R.id.groupIndicator));
+ }
+
+ @MediumTest
+ public void testCallAndGroupViews_ChildView() {
+ mCursor.moveToFirst();
+ insert(CallerInfo.PRIVATE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ View view = mAdapter.newChildView(getActivity(), mParentView);
+ mAdapter.bindChildView(view, getActivity(), mCursor);
+ assertNotNull(view.findViewById(R.id.call_icon));
+ assertNull(view.findViewById(R.id.groupIndicator));
+ }
+
+ @MediumTest
+ public void testBindView_NumberOnly() {
+ mCursor.moveToFirst();
+ insert(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE);
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, TEST_FORMATTED_PHONE_NUMBER);
+ assertNumberLabelIsGone(views);
+ assertNumberIsGone(views);
+ }
+
+ @MediumTest
+ public void testBindView_WithCachedName() {
+ mCursor.moveToFirst();
+ insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ "John Doe", Phone.TYPE_HOME, "");
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, "John Doe");
+ assertNumberLabelIsVisible(views);
+ assertNumberIs(views, TEST_FORMATTED_PHONE_NUMBER);
+ }
+
+ @MediumTest
+ public void testBindView_UriNumber() {
+ mCursor.moveToFirst();
+ insertWithCachedValues("sip:johndoe@gmail.com", NOW, 0, Calls.INCOMING_TYPE,
+ "John Doe", Phone.TYPE_HOME, "");
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, "John Doe");
+ assertNumberLabelIsInvisible(views);
+ assertNumberIs(views, "sip:johndoe@gmail.com");
+ }
+
+ @MediumTest
+ public void testBindView_HomeLabel() {
+ mCursor.moveToFirst();
+ insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ "John Doe", Phone.TYPE_HOME, "");
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, "John Doe");
+ assertNumberLabelIs(views, getTypeLabel(Phone.TYPE_HOME));
+ assertNumberIsVisible(views);
+ }
+
+ @MediumTest
+ public void testBindView_WorkLabel() {
+ mCursor.moveToFirst();
+ insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ "John Doe", Phone.TYPE_WORK, "");
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, "John Doe");
+ assertNumberLabelIs(views, getTypeLabel(Phone.TYPE_WORK));
+ assertNumberIsVisible(views);
+ }
+
+ @MediumTest
+ public void testBindView_CustomLabel() {
+ mCursor.moveToFirst();
+ String numberLabel = "My label";
+ insertWithCachedValues(TEST_PHONE_NUMBER, NOW, 0, Calls.INCOMING_TYPE,
+ "John Doe", Phone.TYPE_CUSTOM, numberLabel);
+ View view = mAdapter.newStandAloneView(getActivity(), mParentView);
+ mAdapter.bindStandAloneView(view, getActivity(), mCursor);
+
+ CallLogListItemViews views = (CallLogListItemViews) view.getTag();
+ assertNameIs(views, "John Doe");
+ assertNumberLabelIs(views, numberLabel);
+ assertNumberIsVisible(views);
+ }
+
+ /** Returns the label associated with a given phone type. */
+ private CharSequence getTypeLabel(int phoneType) {
+ return Phone.getTypeLabel(getActivity().getResources(), phoneType, "");
+ }
+
+ //
+ // HELPERS to check conditions on the DB/views
+ //
+ /**
+ * Check the date of the current list item.
+ * @param date That should be present in the call log list
+ * item. Only NOW is supported.
+ */
+ private void checkDate(long date) {
+ if (NOW == date) {
+ assertEquals("0 mins ago", mItem.dateView.getText());
+ }
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Checks the right icon is used to represent the call type
+ * (missed, incoming, outgoing.) in the current item.
+ */
+ private void checkCallType(int type) {
+ Bitmap icon = ((BitmapDrawable) mItem.iconView.getDrawable()).getBitmap();
+ assertEquals(mCallTypeIcons.get(type), icon);
+ }
+
+ /**
+ * Go over all the views in the list and check that the Call
+ * icon's visibility matches the nature of the number.
+ */
+ private void checkCallStatus() {
+ for (int i = 0; i < mList.length; i++) {
+ if (null == mList[i]) {
+ break;
+ }
+ mItem = (CallLogFragment.CallLogListItemViews) mList[i].getTag();
+
+ // callView tag is the phone number.
+ String number = (String) mItem.callView.getTag();
+
+ if (CallerInfo.PRIVATE_NUMBER.equals(number) ||
+ CallerInfo.UNKNOWN_NUMBER.equals(number)) {
+ assertFalse(View.VISIBLE == mItem.callView.getVisibility());
+ } else {
+ assertEquals(View.VISIBLE, mItem.callView.getVisibility());
+ }
+ }
+ }
+
+
+ //
+ // HELPERS to setup the tests.
+ //
+
+ /**
+ * Get the Bitmap from the icons in the contacts package.
+ */
+ private Bitmap getBitmap(String resName) {
+ Resources r = mActivity.getResources();
+ int resid = r.getIdentifier(resName, "drawable", "com.android.contacts");
+ BitmapDrawable d = (BitmapDrawable) r.getDrawable(resid);
+ assertNotNull(d);
+ return d.getBitmap();
+ }
+
+ /**
+ * Fetch all the icons we need in tests from the contacts app and store them in a map.
+ */
+ private void buildIconMap() {
+ mCallTypeIcons = new HashMap<Integer, Bitmap>(3);
+
+ mCallTypeIcons.put(Calls.INCOMING_TYPE, getBitmap("ic_call_log_list_incoming_call"));
+ mCallTypeIcons.put(Calls.MISSED_TYPE, getBitmap("ic_call_log_list_missed_call"));
+ mCallTypeIcons.put(Calls.OUTGOING_TYPE, getBitmap("ic_call_log_list_outgoing_call"));
+ }
+
+ //
+ // HELPERS to build/update the call entries (views) from the DB.
+ //
+
+ /**
+ * Read the DB and foreach call either update the existing view if
+ * one exists already otherwise create one.
+ * The list is build from a DESC view of the DB (last inserted entry is first).
+ */
+ private void buildViewListFromDb() {
+ int i = 0;
+ mCursor.moveToLast();
+ while(!mCursor.isBeforeFirst()) {
+ if (null == mList[i]) {
+ mList[i] = mAdapter.newStandAloneView(mActivity, mParentView);
+ }
+ mAdapter.bindStandAloneView(mList[i], mActivity, mCursor);
+ mCursor.moveToPrevious();
+ i++;
+ }
+ }
+
+ //
+ // HELPERS to insert numbers in the call log DB.
+ //
+
+ /**
+ * Insert a certain number of random numbers in the DB. Makes sure
+ * there is at least one private and one unknown number in the DB.
+ * @param num Of entries to be inserted.
+ */
+ private void insertRandomEntries(int num) {
+ if (num < 10) {
+ throw new IllegalArgumentException("num should be >= 10");
+ }
+ boolean privateOrUnknownOrVm[];
+ privateOrUnknownOrVm = insertRandomRange(0, num - 2);
+
+ if (privateOrUnknownOrVm[0] && privateOrUnknownOrVm[1]) {
+ insertRandomRange(num - 2, num);
+ } else {
+ insertPrivate(NOW, RAND_DURATION);
+ insertUnknown(NOW, RAND_DURATION);
+ }
+ }
+
+ /**
+ * Insert a new call entry in the test DB.
+ *
+ * It includes the values for the cached contact associated with the number.
+ *
+ * @param number The phone number. For unknown and private numbers,
+ * use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ * @param type Either Call.OUTGOING_TYPE or Call.INCOMING_TYPE or Call.MISSED_TYPE.
+ * @param cachedName the name of the contact with this number
+ * @param cachedNumberType the type of the number, from the contact with this number
+ * @param cachedNumberLabel the label of the number, from the contact with this number
+ */
+ private void insertWithCachedValues(String number, long date, int duration, int type,
+ String cachedName, int cachedNumberType, String cachedNumberLabel) {
+ MatrixCursor.RowBuilder row = mCursor.newRow();
+ row.add(mIndex);
+ mIndex ++;
+ row.add(number);
+ if (NOW == date) {
+ row.add(new Date().getTime());
+ } else {
+ row.add(date);
+ }
+ if (duration < 0) {
+ duration = mRnd.nextInt(10 * 60); // 0 - 10 minutes random.
+ }
+ row.add(duration); // duration
+ if (mVoicemail != null && mVoicemail.equals(number)) {
+ assertEquals(Calls.OUTGOING_TYPE, type);
+ }
+ row.add(type); // type
+ row.add(cachedName); // cached name
+ row.add(cachedNumberType); // cached number type
+ row.add(cachedNumberLabel); // cached number label
+ row.add("US"); // country ISO
+ }
+
+ /**
+ * Insert a new call entry in the test DB.
+ * @param number The phone number. For unknown and private numbers,
+ * use CallerInfo.UNKNOWN_NUMBER or CallerInfo.PRIVATE_NUMBER.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ * @param type Either Call.OUTGOING_TYPE or Call.INCOMING_TYPE or Call.MISSED_TYPE.
+ */
+ private void insert(String number, long date, int duration, int type) {
+ insertWithCachedValues(number, date, duration, type, "", Phone.TYPE_HOME, "");
+ }
+
+ /**
+ * Insert a new private call entry in the test DB.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ */
+ private void insertPrivate(long date, int duration) {
+ insert(CallerInfo.PRIVATE_NUMBER, date, duration, Calls.INCOMING_TYPE);
+ }
+
+ /**
+ * Insert a new unknown call entry in the test DB.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ */
+ private void insertUnknown(long date, int duration) {
+ insert(CallerInfo.UNKNOWN_NUMBER, date, duration, Calls.INCOMING_TYPE);
+ }
+
+ /**
+ * Insert a new voicemail call entry in the test DB.
+ * @param date In millisec since epoch. Use NOW to use the current time.
+ * @param duration In seconds of the call. Use RAND_DURATION to pick a random one.
+ */
+ private void insertVoicemail(long date, int duration) {
+ // mVoicemail may be null
+ if (mVoicemail != null) {
+ insert(mVoicemail, date, duration, Calls.OUTGOING_TYPE);
+ }
+ }
+
+ /**
+ * Insert a range [start, end) of random numbers in the DB. For
+ * each row, there is a 1/10 probability that the number will be
+ * marked as PRIVATE or UNKNOWN or VOICEMAIL. For regular numbers, a number is
+ * inserted, its last 4 digits will be the number of the iteration
+ * in the range.
+ * @param start Of the range.
+ * @param end Of the range (excluded).
+ * @return An array with 2 booleans [0 = private number, 1 =
+ * unknown number, 2 = voicemail] to indicate if at least one
+ * private or unknown or voicemail number has been inserted. Since
+ * the numbers are random some tests may want to enforce the
+ * insertion of such numbers.
+ */
+ // TODO: Should insert numbers with contact entries too.
+ private boolean[] insertRandomRange(int start, int end) {
+ boolean[] privateOrUnknownOrVm = new boolean[] {false, false, false};
+
+ for (int i = start; i < end; i++ ) {
+ int type = mRnd.nextInt(10);
+
+ if (0 == type) {
+ insertPrivate(NOW, RAND_DURATION);
+ privateOrUnknownOrVm[0] = true;
+ } else if (1 == type) {
+ insertUnknown(NOW, RAND_DURATION);
+ privateOrUnknownOrVm[1] = true;
+ } else if (2 == type) {
+ insertVoicemail(NOW, RAND_DURATION);
+ privateOrUnknownOrVm[2] = true;
+ } else {
+ int inout = mRnd.nextBoolean() ? Calls.OUTGOING_TYPE : Calls.INCOMING_TYPE;
+ String number = new Formatter().format("1800123%04d", i).toString();
+ insert(number, NOW, RAND_DURATION, inout);
+ }
+ }
+ return privateOrUnknownOrVm;
+ }
+
+ /** Asserts that the name text view is shown and contains the given text. */
+ private void assertNameIs(CallLogListItemViews views, String name) {
+ assertEquals(View.VISIBLE, views.line1View.getVisibility());
+ assertEquals(name, views.line1View.getText());
+ }
+
+ /** Asserts that the number label text view is shown and contains the given text. */
+ private void assertNumberLabelIs(CallLogListItemViews views, CharSequence numberLabel) {
+ assertNumberLabelIsVisible(views);
+ assertEquals(numberLabel, views.labelView.getText());
+ }
+
+ /** Asserts that the number label text view is shown. */
+ private void assertNumberLabelIsVisible(CallLogListItemViews views) {
+ assertEquals(View.VISIBLE, views.labelView.getVisibility());
+ }
+
+ /** Asserts that the number label text view is invisible. */
+ private void assertNumberLabelIsInvisible(CallLogListItemViews views) {
+ assertEquals(View.INVISIBLE, views.labelView.getVisibility());
+ }
+
+ /** Asserts that the number label text view is gone. */
+ private void assertNumberLabelIsGone(CallLogListItemViews views) {
+ assertEquals(View.GONE, views.labelView.getVisibility());
+ }
+
+ /** Asserts that the number text view is shown and contains the given text. */
+ private void assertNumberIs(CallLogListItemViews views, String number) {
+ assertNumberIsVisible(views);
+ assertEquals(number, views.numberView.getText());
+ }
+
+ /** Asserts that the number text view is shown. */
+ private void assertNumberIsVisible(CallLogListItemViews views) {
+ assertEquals(View.VISIBLE, views.numberView.getVisibility());
+ }
+
+ /** Asserts that the number text view is gone. */
+ private void assertNumberIsGone(CallLogListItemViews views) {
+ assertEquals(View.GONE, views.numberView.getVisibility());
+ }
+}
diff --git a/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
similarity index 91%
rename from tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java
rename to tests/src/com/android/contacts/activities/PeopleActivityTest.java
index 912950f..4c1bb16 100644
--- a/tests/src/com/android/contacts/activities/ContactBrowserActivityTest.java
+++ b/tests/src/com/android/contacts/activities/PeopleActivityTest.java
@@ -16,6 +16,7 @@
package com.android.contacts.activities;
+import com.android.contacts.ContactPhotoManager;
import com.android.contacts.ContactsApplication;
import com.android.contacts.R;
import com.android.contacts.detail.ContactDetailFragment;
@@ -26,9 +27,11 @@
import com.android.contacts.test.InjectedServices;
import com.android.contacts.tests.mocks.ContactsMockContext;
import com.android.contacts.tests.mocks.MockAccountTypeManager;
+import com.android.contacts.tests.mocks.MockContactPhotoManager;
import com.android.contacts.tests.mocks.MockContentProvider;
import com.android.contacts.tests.mocks.MockContentProvider.Query;
import com.android.contacts.tests.mocks.MockSharedPreferences;
+import com.android.contacts.util.PhoneCapabilityTester;
import android.accounts.Account;
import android.content.ContentValues;
@@ -48,7 +51,7 @@
import android.widget.TextView;
/**
- * Tests for {@link ContactBrowserActivity}.
+ * Tests for {@link PeopleActivity}.
*
* Running all tests:
*
@@ -58,8 +61,8 @@
* -w com.android.contacts.tests/android.test.InstrumentationTestRunner
*/
@Smoke
-public class ContactBrowserActivityTest
- extends ActivityInstrumentationTestCase2<ContactBrowserActivity>
+public class PeopleActivityTest
+ extends ActivityInstrumentationTestCase2<PeopleActivity>
{
static {
// AsyncTask class needs to be initialized on the main thread.
@@ -73,8 +76,8 @@
private MockContentProvider mContactsProvider;
private MockContentProvider mSettingsProvider;
- public ContactBrowserActivityTest() {
- super(ContactBrowserActivity.class);
+ public PeopleActivityTest() {
+ super(PeopleActivity.class);
}
@Override
@@ -85,7 +88,8 @@
InjectedServices services = new InjectedServices();
services.setContentResolver(mContext.getContentResolver());
services.setSharedPreferences(new MockSharedPreferences());
-
+ services.setSystemService(ContactPhotoManager.CONTACT_PHOTO_SERVICE,
+ new MockContactPhotoManager());
AccountType accountType = new BaseAccountType();
accountType.accountType = TEST_ACCOUNT_TYPE;
@@ -98,6 +102,10 @@
}
public void testSingleAccountNoGroups() {
+ // This two-pane UI test only makes sense if we run with two panes.
+ // Let's ignore this in the single pane case
+ if (!PhoneCapabilityTester.isUsingTwoPanes(mContext)) return;
+
expectSettingsQueriesAndReturnDefault();
expectProviderStatusQueryAndReturnNormal();
expectGroupsQueryAndReturnEmpty();
@@ -107,7 +115,7 @@
setActivityIntent(new Intent(Intent.ACTION_DEFAULT));
- ContactBrowserActivity activity = getActivity();
+ PeopleActivity activity = getActivity();
getInstrumentation().waitForIdleSync();
diff --git a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
index 4cee32c..cfab94a 100644
--- a/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
+++ b/tests/src/com/android/contacts/detail/ContactDetailFragmentTests.java
@@ -16,7 +16,7 @@
package com.android.contacts.detail;
-import com.android.contacts.detail.ContactDetailFragment.ViewEntry;
+import com.android.contacts.detail.ContactDetailFragment.DetailViewEntry;
import android.content.ContentValues;
import android.content.Intent;
@@ -42,7 +42,7 @@
values.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
values.put(Im.DATA, TEST_ADDRESS);
- ViewEntry entry = new ContactDetailFragment.ViewEntry();
+ DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
ContactDetailFragment.buildImActions(entry, values);
assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
@@ -59,7 +59,7 @@
values.put(Im.DATA, TEST_ADDRESS);
values.put(Im.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO);
- ViewEntry entry = new ContactDetailFragment.ViewEntry();
+ DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
ContactDetailFragment.buildImActions(entry, values);
assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
@@ -78,7 +78,7 @@
values.put(Im.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO |
Im.CAPABILITY_HAS_VOICE);
- ViewEntry entry = new ContactDetailFragment.ViewEntry();
+ DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
ContactDetailFragment.buildImActions(entry, values);
assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
@@ -97,7 +97,7 @@
values.put(Im.CUSTOM_PROTOCOL, TEST_PROTOCOL);
values.put(Im.DATA, TEST_ADDRESS);
- ViewEntry entry = new ContactDetailFragment.ViewEntry();
+ DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
ContactDetailFragment.buildImActions(entry, values);
assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
@@ -120,7 +120,7 @@
values.put(Email.CHAT_CAPABILITY, Im.CAPABILITY_HAS_VOICE | Im.CAPABILITY_HAS_VIDEO |
Im.CAPABILITY_HAS_VOICE);
- ViewEntry entry = new ContactDetailFragment.ViewEntry();
+ DetailViewEntry entry = new ContactDetailFragment.DetailViewEntry();
ContactDetailFragment.buildImActions(entry, values);
assertEquals(Intent.ACTION_SENDTO, entry.intent.getAction());
assertEquals("xmpp:" + TEST_ADDRESS + "?message", entry.intent.getData().toString());
diff --git a/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java b/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java
new file mode 100644
index 0000000..fb834c0
--- /dev/null
+++ b/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+
+import android.provider.ContactsContract;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.widget.TextView;
+
+/**
+ * Unit tests for {@link DisplayNameFormatter}.
+ */
+@SmallTest
+public class DisplayNameFormatterTest extends AndroidTestCase {
+ private static final int TEST_PREFIX_HIGHLIGHT_COLOR = 0xFF0000;
+ /** The HTML code used to mark the start of the highlighted part. */
+ private static final String START = "<font color =\"#1ff0000\">";
+ /** The HTML code used to mark the end of the highlighted part. */
+ private static final String END = "</font>";
+
+ private PrefixHighlighter mPrefixHighlighter;
+ /** The object under test. */
+ private DisplayNameFormatter mDisplayNameFormatter;
+ /** The view to on which the text is set. */
+ private TextView mView;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPrefixHighlighter = new PrefixHighlighter(TEST_PREFIX_HIGHLIGHT_COLOR);
+ mDisplayNameFormatter = new DisplayNameFormatter(mPrefixHighlighter);
+ mView = new TextView(getContext());
+ // This guarantees that the text will be stored as a Spannable so that we can determine
+ // which styles have been applied to it.
+ mView.setText("", TextView.BufferType.SPANNABLE);
+ }
+
+ public void testSetDisplayName_Simple() {
+ setNames("John Doe", "Doe John");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("<b>John </b>Doe", mView);
+ setNames("Jean Pierre Doe", "Doe Jean Pierre");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("<b>Jean Pierre </b>Doe", mView);
+ setNames("John Doe Smith", "Doe Smith John");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("<b>John </b>Doe Smith", mView);
+ }
+ public void testSetDisplayName_AccidentalOverlap() {
+ // This is probably not what we want, but we assume that the two names differ only in the
+ // order in which the two components are listed.
+ setNames("Johnson John", "Johnson Smith");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("<b>Johnson </b>John", mView);
+ }
+
+ public void testSetDisplayName_Reversed() {
+ setNames("John Doe", "Doe John");
+ setDisplayNameReversed();
+ SpannedTestUtils.checkHtmlText("John <b>Doe</b>", mView);
+ setNames("Jean Pierre Doe", "Doe Jean Pierre");
+ setDisplayNameReversed();
+ SpannedTestUtils.checkHtmlText("Jean Pierre <b>Doe</b>", mView);
+ setNames("John Doe Smith", "Doe Smith John");
+ setDisplayNameReversed();
+ SpannedTestUtils.checkHtmlText("John <b>Doe Smith</b>", mView);
+ }
+
+ public void testSetDisplayName_NoOverlap() {
+ setNames("John Smith", "Doe Albert");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("John Smith", mView);
+ }
+
+ public void testSetDisplayName_Prefix() {
+ setNames("John Doe", "Doe John");
+ setDisplayNameWithPrefix("DO");
+ SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "Do" + END + "e", mView);
+ }
+
+ public void testSetDisplayName_PrefixFirstName() {
+ setNames("John Doe", "Doe John");
+ setDisplayNameWithPrefix("JO");
+ SpannedTestUtils.checkHtmlText(START + "<b>Jo</b>" + END + "<b>hn </b>Doe", mView);
+ }
+
+ public void testSetDisplayName_PrefixMiddleName() {
+ setNames("John Paul Doe", "Doe John Paul");
+ setDisplayNameWithPrefix("PAU");
+ SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "<b>Pau</b>" + END + "<b>l </b>Doe",
+ mView);
+ }
+
+ public void testSetDisplayName_ReversedPrefix() {
+ setNames("John Doe", "Doe John");
+ setDisplayNameReversedWithPrefix("DO");
+ SpannedTestUtils.checkHtmlText("John " + START + "<b>Do</b>" + END + "<b>e</b>", mView);
+ }
+
+ public void testSetDisplayName_Empty() {
+ setNames("", "");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("", mView);
+ }
+
+ public void testSetDisplayName_Unknown() {
+ mDisplayNameFormatter.setUnknownNameText("unknown");
+ setNames("", "");
+ setDisplayName();
+ SpannedTestUtils.checkHtmlText("unknown", mView);
+ }
+
+ public void testSetDisplayName_Highlighting() {
+ mDisplayNameFormatter.setTextWithHighlightingFactory(new TestTextWithHighlightingFactory());
+ setNames("John Doe", "Sue Anne");
+ setDisplayNameWithHighlighting();
+ SpannedTestUtils.checkHtmlText("<i>John Doe</i> <i>Sue Anne</i>", mView);
+ }
+
+ public void testSetDisplayName_HighlightingAndBoldFirstName() {
+ mDisplayNameFormatter.setTextWithHighlightingFactory(new TestTextWithHighlightingFactory());
+ setNames("John Doe", "Doe John");
+ setDisplayNameWithHighlighting();
+ SpannedTestUtils.checkHtmlText("<i><b>John </b></i><i>Doe</i> <i>Doe John</i>", mView);
+ }
+
+ /**
+ * Sets the name and alternate name on the formatter.
+ *
+ * @param name the name to be display
+ * @param alternateName the alternate name to be displayed
+ */
+ private void setNames(String name, String alternateName) {
+ FormatUtils.copyToCharArrayBuffer(name, mDisplayNameFormatter.getNameBuffer());
+ FormatUtils.copyToCharArrayBuffer(alternateName,
+ mDisplayNameFormatter.getAlternateNameBuffer());
+ }
+
+ /**
+ * Sets the display name on the text view.
+ */
+ private void setDisplayName() {
+ mDisplayNameFormatter.setDisplayName(mView,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY, false, null);
+ }
+
+ /**
+ * Sets the display name on the text view using the reverted order.
+ */
+ private void setDisplayNameReversed() {
+ mDisplayNameFormatter.setDisplayName(mView,
+ ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE, false, null);
+ }
+
+ /**
+ * Sets the display name on the text view with prefix highlighting enabled.
+ */
+ private void setDisplayNameWithPrefix(String prefix) {
+ mDisplayNameFormatter.setDisplayName(mView,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY, false, prefix.toCharArray());
+ }
+
+ /**
+ * Sets the display name reversed on the text view with prefix highlighting enabled.
+ */
+ private void setDisplayNameReversedWithPrefix(String prefix) {
+ mDisplayNameFormatter.setDisplayName(mView,
+ ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE, false,
+ prefix.toCharArray());
+ }
+
+ /**
+ * Sets the display name on the text view with highlighting enabled.
+ */
+ private void setDisplayNameWithHighlighting() {
+ mDisplayNameFormatter.setDisplayName(mView,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY, true, null);
+ }
+}
diff --git a/tests/src/com/android/contacts/format/FormatUtilsTests.java b/tests/src/com/android/contacts/format/FormatUtilsTests.java
new file mode 100644
index 0000000..42e2d53
--- /dev/null
+++ b/tests/src/com/android/contacts/format/FormatUtilsTests.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import android.database.CharArrayBuffer;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+/**
+ * Test cases for format utility methods.
+ */
+@SmallTest
+public class FormatUtilsTests extends AndroidTestCase {
+
+ public void testOverlapPoint() throws Exception {
+ assertEquals(2, FormatUtils.overlapPoint("abcde", "cdefg"));
+ assertEquals(-1, FormatUtils.overlapPoint("John Doe", "John Doe"));
+ assertEquals(5, FormatUtils.overlapPoint("John Doe", "Doe, John"));
+ assertEquals(-1, FormatUtils.overlapPoint("Mr. John Doe", "Mr. Doe, John"));
+ assertEquals(13, FormatUtils.overlapPoint("John Herbert Doe", "Doe, John Herbert"));
+ }
+
+ public void testCopyToCharArrayBuffer() {
+ CharArrayBuffer charArrayBuffer = new CharArrayBuffer(20);
+ checkCopyToCharArrayBuffer(charArrayBuffer, null, 0);
+ checkCopyToCharArrayBuffer(charArrayBuffer, "", 0);
+ checkCopyToCharArrayBuffer(charArrayBuffer, "test", 4);
+ // Check that it works after copying something into it.
+ checkCopyToCharArrayBuffer(charArrayBuffer, "", 0);
+ checkCopyToCharArrayBuffer(charArrayBuffer, "test", 4);
+ checkCopyToCharArrayBuffer(charArrayBuffer, null, 0);
+ // This requires a resize of the actual buffer.
+ checkCopyToCharArrayBuffer(charArrayBuffer, "test test test test test", 24);
+ }
+
+ public void testCharArrayBufferToString() {
+ checkCharArrayBufferToString("");
+ checkCharArrayBufferToString("test");
+ checkCharArrayBufferToString("test test test test test");
+ }
+
+ /** Checks that copying a string into a {@link CharArrayBuffer} and back works correctly. */
+ private void checkCharArrayBufferToString(String text) {
+ CharArrayBuffer buffer = new CharArrayBuffer(20);
+ FormatUtils.copyToCharArrayBuffer(text, buffer);
+ assertEquals(text, FormatUtils.charArrayBufferToString(buffer));
+ }
+
+ /**
+ * Checks that copying into the char array buffer copies the values correctly.
+ */
+ private void checkCopyToCharArrayBuffer(CharArrayBuffer buffer, String value, int length) {
+ FormatUtils.copyToCharArrayBuffer(value, buffer);
+ assertEquals(length, buffer.sizeCopied);
+ for (int index = 0; index < length; ++index) {
+ assertEquals(value.charAt(index), buffer.data[index]);
+ }
+ }
+
+ public void testIndexOfWordPrefix_MatchingPrefix() {
+ checkIndexOfWordPrefix("test", "TE", 0);
+ checkIndexOfWordPrefix("Test", "TE", 0);
+ checkIndexOfWordPrefix("TEst", "TE", 0);
+ checkIndexOfWordPrefix("TEST", "TE", 0);
+ checkIndexOfWordPrefix("a test", "TE", 2);
+ checkIndexOfWordPrefix("test test", "TE", 0);
+ checkIndexOfWordPrefix("a test test", "TE", 2);
+ }
+
+ public void testIndexOfWordPrefix_NotMatchingPrefix() {
+ checkIndexOfWordPrefix("test", "TA", -1);
+ checkIndexOfWordPrefix("test type theme", "TA", -1);
+ checkIndexOfWordPrefix("atest retest pretest", "TEST", -1);
+ checkIndexOfWordPrefix("tes", "TEST", -1);
+ }
+
+ public void testIndexOfWordPrefix_LowerCase() {
+ // The prefix match only works if the prefix is un upper case.
+ checkIndexOfWordPrefix("test", "te", -1);
+ }
+
+ /**
+ * Checks that getting the index of a word prefix in the given text returns the expected index.
+ *
+ * @param text the text in which to look for the word
+ * @param wordPrefix the word prefix to look for
+ * @param expectedIndex the expected value to be returned by the function
+ */
+ private void checkIndexOfWordPrefix(String text, String wordPrefix, int expectedIndex) {
+ assertEquals(expectedIndex, FormatUtils.indexOfWordPrefix(text, wordPrefix.toCharArray()));
+ }
+}
diff --git a/tests/src/com/android/contacts/format/PrefixHighligherTest.java b/tests/src/com/android/contacts/format/PrefixHighligherTest.java
new file mode 100644
index 0000000..5500abf
--- /dev/null
+++ b/tests/src/com/android/contacts/format/PrefixHighligherTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import android.database.CharArrayBuffer;
+import android.test.AndroidTestCase;
+import android.widget.TextView;
+
+/**
+ * Unit tests for {@link PrefixHighlighter}.
+ */
+public class PrefixHighligherTest extends AndroidTestCase {
+ private static final int TEST_PREFIX_HIGHLIGHT_COLOR = 0xFF0000;
+ /** The HTML code used to mark the start of the highlighted part. */
+ private static final String START = "<font color =\"#1ff0000\">";
+ /** The HTML code used to mark the end of the highlighted part. */
+ private static final String END = "</font>";
+
+ /** The object under test. */
+ private PrefixHighlighter mPrefixHighlighter;
+ /** The view to on which the text is set. */
+ private TextView mView;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mPrefixHighlighter = new PrefixHighlighter(TEST_PREFIX_HIGHLIGHT_COLOR);
+ mView = new TextView(getContext());
+ // This guarantees that the text will be stored as a spannable so that we can determine
+ // which styles have been applied to it.
+ mView.setText("", TextView.BufferType.SPANNABLE);
+ }
+
+ public void testSetText_EmptyPrefix() {
+ mPrefixHighlighter.setText(mView, "", new char[0]);
+ SpannedTestUtils.checkHtmlText("", mView);
+
+ mPrefixHighlighter.setText(mView, "test", new char[0]);
+ SpannedTestUtils.checkHtmlText("test", mView);
+ }
+
+ public void testSetText_MatchingPrefix() {
+ mPrefixHighlighter.setText(mView, "test", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText(START + "te" + END + "st", mView);
+
+ mPrefixHighlighter.setText(mView, "Test", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText(START + "Te" + END + "st", mView);
+
+ mPrefixHighlighter.setText(mView, "TEst", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText(START + "TE" + END + "st", mView);
+
+ mPrefixHighlighter.setText(mView, "a test", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("a " + START + "te" + END + "st", mView);
+ }
+
+ public void testSetText_NotMatchingPrefix() {
+ mPrefixHighlighter.setText(mView, "test", "TA".toCharArray());
+ SpannedTestUtils.checkHtmlText("test", mView);
+ }
+
+ public void testSetText_FirstMatch() {
+ mPrefixHighlighter.setText(mView, "a test's tests are not tests", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("a " +START + "te" + END + "st's tests are not tests",
+ mView);
+ }
+
+ public void testSetText_NoMatchingMiddleOfWord() {
+ mPrefixHighlighter.setText(mView, "atest", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("atest", mView);
+
+ mPrefixHighlighter.setText(mView, "atest otest", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("atest otest", mView);
+
+ mPrefixHighlighter.setText(mView, "atest test", "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("atest " + START + "te" + END + "st", mView);
+ }
+
+ public void testSetText_CharArrayBuffer() {
+ CharArrayBuffer buffer = new CharArrayBuffer(100);
+
+ FormatUtils.copyToCharArrayBuffer("test", buffer);
+ mPrefixHighlighter.setText(mView, buffer, new char[0]);
+ SpannedTestUtils.checkHtmlText("test", mView);
+
+ FormatUtils.copyToCharArrayBuffer("a test", buffer);
+ mPrefixHighlighter.setText(mView, buffer, "TE".toCharArray());
+ SpannedTestUtils.checkHtmlText("a " + START + "te" + END + "st", mView);
+
+ FormatUtils.copyToCharArrayBuffer("test", buffer);
+ mPrefixHighlighter.setText(mView, buffer, "TA".toCharArray());
+ SpannedTestUtils.checkHtmlText("test", mView);
+ }
+}
diff --git a/tests/src/com/android/contacts/format/SpannedTestUtils.java b/tests/src/com/android/contacts/format/SpannedTestUtils.java
new file mode 100644
index 0000000..625c6aa
--- /dev/null
+++ b/tests/src/com/android/contacts/format/SpannedTestUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import android.text.Html;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.widget.TextView;
+
+import junit.framework.Assert;
+
+/**
+ * Utility class to check the value of spanned text in text views.
+ */
+public class SpannedTestUtils {
+ /**
+ * Checks that the text contained in the text view matches the given HTML text.
+ *
+ * @param expectedHtmlText the expected text to be in the text view
+ * @param textView the text view from which to get the text
+ */
+ public static void checkHtmlText(String expectedHtmlText, TextView textView) {
+ String actualHtmlText = Html.toHtml((Spanned) textView.getText());
+ if (TextUtils.isEmpty(expectedHtmlText)) {
+ // If the text is empty, it does not add the <p></p> bits to it.
+ Assert.assertEquals("", actualHtmlText);
+ } else {
+ Assert.assertEquals("<p>" + expectedHtmlText + "</p>\n", actualHtmlText);
+ }
+ }
+
+}
diff --git a/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java b/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java
new file mode 100644
index 0000000..f2848d0
--- /dev/null
+++ b/tests/src/com/android/contacts/format/TestTextWithHighlightingFactory.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.format;
+
+import com.android.contacts.widget.TextWithHighlighting;
+import com.android.contacts.widget.TextWithHighlightingFactory;
+
+import android.database.CharArrayBuffer;
+import android.graphics.Typeface;
+import android.text.SpannableStringBuilder;
+import android.text.style.StyleSpan;
+
+/** A factory for {@link TextWithHighlighting} that wraps its parts in italics. */
+public final class TestTextWithHighlightingFactory implements TextWithHighlightingFactory {
+ /** A {@link TextWithHighlighting} implementation that wraps its parts in italics. */
+ private final static class TestTextWithHighlighting extends SpannableStringBuilder
+ implements TextWithHighlighting {
+ @Override
+ public void setText(CharArrayBuffer baseText, CharArrayBuffer highlightedText) {
+ append(new String(baseText.data, 0, baseText.sizeCopied));
+ append(' ');
+ append(new String(highlightedText.data, 0, highlightedText.sizeCopied));
+ setSpan(new StyleSpan(Typeface.ITALIC), 0, baseText.sizeCopied, 0);
+ setSpan(new StyleSpan(Typeface.ITALIC), baseText.sizeCopied + 1,
+ baseText.sizeCopied + 1 + highlightedText.sizeCopied, 0);
+ }
+ }
+
+ @Override
+ public TextWithHighlighting createTextWithHighlighting() {
+ return new TestTextWithHighlighting();
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java b/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
index 43e844e..c401a8c 100644
--- a/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
+++ b/tests/src/com/android/contacts/interactions/PhoneNumberInteractionTest.java
@@ -124,6 +124,26 @@
assertEquals("sms:456", interaction.startedIntent.getDataString());
}
+ public void testShouldCollapseWith() {
+ PhoneNumberInteraction.PhoneItem phoneItem1 = new PhoneNumberInteraction.PhoneItem();
+ PhoneNumberInteraction.PhoneItem phoneItem2 = new PhoneNumberInteraction.PhoneItem();
+
+ phoneItem1.phoneNumber = "123";
+ phoneItem2.phoneNumber = "123";
+
+ assertTrue(phoneItem1.shouldCollapseWith(phoneItem2));
+
+ phoneItem1.phoneNumber = "123";
+ phoneItem2.phoneNumber = "456";
+
+ assertFalse(phoneItem1.shouldCollapseWith(phoneItem2));
+
+ phoneItem1.phoneNumber = "123#,123";
+ phoneItem2.phoneNumber = "123#,456";
+
+ assertFalse(phoneItem1.shouldCollapseWith(phoneItem2));
+ }
+
public void testCallNumberWhenThereAreDuplicates() {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, 13);
expectQuery(contactUri)
diff --git a/tests/src/com/android/contacts/list/ContactListItemViewTest.java b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
new file mode 100644
index 0000000..7764eb3
--- /dev/null
+++ b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.list;
+
+import com.android.contacts.activities.PeopleActivity;
+import com.android.contacts.format.SpannedTestUtils;
+import com.android.contacts.format.TestTextWithHighlightingFactory;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.provider.ContactsContract;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.widget.TextView;
+
+/**
+ * Unit tests for {@link ContactListItemView}.
+ *
+ * It uses an {@link ActivityInstrumentationTestCase2} for {@link PeopleActivity} because we need
+ * to have the style properly setup.
+ */
+@LargeTest
+public class ContactListItemViewTest extends ActivityInstrumentationTestCase2<PeopleActivity> {
+ /** The HTML code used to mark the start of the highlighted part. */
+ private static final String START = "<font color =\"#729a27\">";
+ /** The HTML code used to mark the end of the highlighted part. */
+ private static final String END = "</font>";
+
+ public ContactListItemViewTest() {
+ super(PeopleActivity.class);
+ }
+
+ public void testShowDisplayName_Simple() {
+ Cursor cursor = createCursor("John Doe", "Doe John");
+ ContactListItemView view = createView();
+
+ view.showDisplayName(cursor, 0, 1, false,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+
+ SpannedTestUtils.checkHtmlText("<b>John </b>Doe", view.getNameTextView());
+ }
+
+ public void testShowDisplayName_Unknown() {
+ Cursor cursor = createCursor("", "");
+ ContactListItemView view = createView();
+
+ view.setUnknownNameText("unknown");
+ view.showDisplayName(cursor, 0, 1, false,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+
+ SpannedTestUtils.checkHtmlText("unknown", view.getNameTextView());
+ }
+
+ public void testShowDisplayName_WithPrefix() {
+ Cursor cursor = createCursor("John Doe", "Doe John");
+ ContactListItemView view = createView();
+
+ view.setHighlightedPrefix("DOE".toCharArray());
+ view.showDisplayName(cursor, 0, 1, false,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+
+ SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "Doe" + END,
+ view.getNameTextView());
+ }
+
+ public void testShowDisplayName_WithPrefixReversed() {
+ Cursor cursor = createCursor("John Doe", "Doe John");
+ ContactListItemView view = createView();
+
+ view.setHighlightedPrefix("DOE".toCharArray());
+ view.showDisplayName(cursor, 0, 1, false,
+ ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE);
+
+ SpannedTestUtils.checkHtmlText("John " + START + "<b>Doe</b>" + END,
+ view.getNameTextView());
+ }
+
+ public void testShowDisplayName_WithHighlight() {
+ Cursor cursor = createCursor("John Doe", "Doe John");
+ ContactListItemView view = createView();
+
+ view.setTextWithHighlightingFactory(new TestTextWithHighlightingFactory());
+ view.showDisplayName(cursor, 0, 1, true,
+ ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
+
+ SpannedTestUtils.checkHtmlText("<i><b>John </b></i><i>Doe</i> <i>Doe John</i>",
+ view.getNameTextView());
+ }
+
+ public void testSetSnippet_Prefix() {
+ ContactListItemView view = createView();
+ view.setHighlightedPrefix("TEST".toCharArray());
+ view.setSnippet("This is a test");
+ SpannedTestUtils.checkHtmlText("This is a " + START + "test" + END,
+ view.getSnippetView());
+ }
+
+ /** Creates the view to be tested. */
+ private ContactListItemView createView() {
+ ContactListItemView view = new ContactListItemView(getActivity(), null);
+ // Set the name view to use a Spannable to represent its content.
+ view.getNameTextView().setText("", TextView.BufferType.SPANNABLE);
+ return view;
+ }
+
+ /**
+ * Creates a cursor containing a pair of values.
+ *
+ * @param name the name to insert in the first column of the cursor
+ * @param alternateName the alternate name to insert in the second column of the cursor
+ * @return the newly created cursor
+ */
+ private Cursor createCursor(String name, String alternateName) {
+ MatrixCursor cursor = new MatrixCursor(new String[]{"Name", "AlternateName"});
+ cursor.moveToFirst();
+ cursor.addRow(new Object[]{name, alternateName});
+ return cursor;
+ }
+}
diff --git a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
index 50a1f1f..03b6302 100644
--- a/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
+++ b/tests/src/com/android/contacts/tests/allintents/AllIntentsActivity.java
@@ -73,6 +73,7 @@
ACTION_PICK_PHONE_LEGACY,
ACTION_PICK_POSTAL,
ACTION_PICK_POSTAL_LEGACY,
+ ACTION_PICK_EMAIL,
ACTION_CREATE_SHORTCUT_CONTACT,
ACTION_CREATE_SHORTCUT_DIAL,
ACTION_CREATE_SHORTCUT_MESSAGE,
@@ -195,6 +196,11 @@
startContactSelectionActivityForResult(intent);
break;
}
+ case ACTION_PICK_EMAIL: {
+ startContactSelectionActivityForResult(
+ new Intent(Intent.ACTION_PICK, Email.CONTENT_URI));
+ break;
+ }
case ACTION_CREATE_SHORTCUT_CONTACT: {
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
startContactSelectionActivityForResult(intent);
diff --git a/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
new file mode 100644
index 0000000..6da205b
--- /dev/null
+++ b/tests/src/com/android/contacts/tests/mocks/MockContactPhotoManager.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.tests.mocks;
+
+import com.android.contacts.ContactPhotoManager;
+
+import android.net.Uri;
+import android.widget.ImageView;
+
+/**
+ * A photo preloader that always uses the "no contact" picture and never executes any real
+ * db queries
+ */
+public class MockContactPhotoManager extends ContactPhotoManager {
+ @Override
+ public void loadPhoto(ImageView view, long photoId) {
+ view.setImageResource(mDefaultResourceId);
+ }
+
+ @Override
+ public void loadPhoto(ImageView view, Uri photoUri) {
+ view.setImageResource(mDefaultResourceId);
+ }
+
+ @Override
+ public void pause() {
+ }
+
+ @Override
+ public void resume() {
+ }
+
+ @Override
+ public void refreshCache() {
+ }
+
+ @Override
+ public void preloadPhotosInBackground() {
+ }
+}
diff --git a/tests/src/com/android/contacts/util/NameConverterTests.java b/tests/src/com/android/contacts/util/NameConverterTests.java
new file mode 100644
index 0000000..e1773a7
--- /dev/null
+++ b/tests/src/com/android/contacts/util/NameConverterTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.util;
+
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Tests for {@link NameConverter}.
+ */
+@SmallTest
+public class NameConverterTests extends AndroidTestCase {
+
+ public void testStructuredNameToDisplayName() {
+ Map<String, String> structuredName = new HashMap<String, String>();
+ structuredName.put(StructuredName.PREFIX, "Mr.");
+ structuredName.put(StructuredName.GIVEN_NAME, "John");
+ structuredName.put(StructuredName.MIDDLE_NAME, "Quincy");
+ structuredName.put(StructuredName.FAMILY_NAME, "Adams");
+ structuredName.put(StructuredName.SUFFIX, "Esquire");
+
+ assertEquals("Mr. John Quincy Adams, Esquire",
+ NameConverter.structuredNameToDisplayName(mContext, structuredName));
+
+ structuredName.remove(StructuredName.SUFFIX);
+ assertEquals("Mr. John Quincy Adams",
+ NameConverter.structuredNameToDisplayName(mContext, structuredName));
+
+ structuredName.remove(StructuredName.MIDDLE_NAME);
+ assertEquals("Mr. John Adams",
+ NameConverter.structuredNameToDisplayName(mContext, structuredName));
+ }
+
+ public void testDisplayNameToStructuredName() {
+ assertStructuredName("Mr. John Quincy Adams, Esquire",
+ "Mr.", "John", "Quincy", "Adams", "Esquire");
+ assertStructuredName("John Doe", null, "John", null, "Doe", null);
+ assertStructuredName("Ms. Jane Eyre", "Ms.", "Jane", null, "Eyre", null);
+ assertStructuredName("Dr Leo Spaceman, PhD", "Dr", "Leo", null, "Spaceman", "PhD");
+ }
+
+ /**
+ * Helper method to check whether a given display name parses out to the other parameters.
+ * @param displayName Display name to break into a structured name.
+ * @param prefix Expected prefix (null if not expected).
+ * @param givenName Expected given name (null if not expected).
+ * @param middleName Expected middle name (null if not expected).
+ * @param familyName Expected family name (null if not expected).
+ * @param suffix Expected suffix (null if not expected).
+ */
+ private void assertStructuredName(String displayName, String prefix,
+ String givenName, String middleName, String familyName, String suffix) {
+ Map<String, String> structuredName = NameConverter.displayNameToStructuredName(mContext,
+ displayName);
+ checkNameComponent(StructuredName.PREFIX, prefix, structuredName);
+ checkNameComponent(StructuredName.GIVEN_NAME, givenName, structuredName);
+ checkNameComponent(StructuredName.MIDDLE_NAME, middleName, structuredName);
+ checkNameComponent(StructuredName.FAMILY_NAME, familyName, structuredName);
+ checkNameComponent(StructuredName.SUFFIX, suffix, structuredName);
+ assertEquals(0, structuredName.size());
+ }
+
+ /**
+ * Checks that the given field and value are present in the structured name map (or not present
+ * if the given value is null). If the value is present and matches, the key is removed from
+ * the map - once all components of the name are checked, the map should be empty.
+ * @param field Field to check.
+ * @param value Expected value for the field (null if it is not expected to be populated).
+ * @param structuredName The map of structured field names to values.
+ */
+ private void checkNameComponent(String field, String value,
+ Map<String, String> structuredName) {
+ if (TextUtils.isEmpty(value)) {
+ assertNull(structuredName.get(field));
+ } else {
+ assertEquals(value, structuredName.get(field));
+ }
+ structuredName.remove(field);
+ }
+}