Merge "Import translations. DO NOT MERGE" into jb-mr1.1-dev
diff --git a/res/layout-sw580dp/quickcontact_activity.xml b/res/layout-sw580dp/quickcontact_activity.xml
index a97d86c..129a6e5 100644
--- a/res/layout-sw580dp/quickcontact_activity.xml
+++ b/res/layout-sw580dp/quickcontact_activity.xml
@@ -42,6 +42,7 @@
android:background="@color/quickcontact_tab_indicator" />
<android.support.v4.view.ViewPager
android:id="@+id/item_list_pager"
+ android:background="@color/quickcontact_list_background"
android:layout_width="match_parent"
android:layout_height="160dip" />
</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4e5b215..1ac9b87 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -136,11 +136,11 @@
<!-- Menu item that deletes the currently selected group [CHAR LIMIT=30] -->
<string name="menu_deleteGroup">Delete</string>
- <!-- Menu item (in the action bar) that creates a new contacts [CHAR LIMIT=12] -->
- <string name="menu_new_contact_action_bar">New</string>
+ <!-- Menu item (in the action bar) that creates a new contact [CHAR LIMIT=30] -->
+ <string name="menu_new_contact_action_bar">Add Contact</string>
- <!-- Menu item (in the action bar) that creates a new group [CHAR LIMIT=12] -->
- <string name="menu_new_group_action_bar">New</string>
+ <!-- Menu item (in the action bar) that creates a new group [CHAR LIMIT=30] -->
+ <string name="menu_new_group_action_bar">Add Group</string>
<!-- Title of the confirmation dialog for separating contacts into multiple instances [CHAR LIMIT=26] -->
<string name="splitConfirmation_title">Separate contact?</string>
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index a310b88..855c134 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -271,14 +271,12 @@
mDigitsContainer = fragmentView.findViewById(R.id.digits_container);
mDigits = (EditText) fragmentView.findViewById(R.id.digits);
- mDigits.setKeyListener(DialerKeyListener.getInstance());
+ mDigits.setKeyListener(UnicodeDialerKeyListener.INSTANCE);
mDigits.setOnClickListener(this);
mDigits.setOnKeyListener(this);
mDigits.setOnLongClickListener(this);
mDigits.addTextChangedListener(this);
-
PhoneNumberFormatter.setPhoneNumberFormattingTextWatcher(getActivity(), mDigits);
-
// Check for the presence of the keypad
View oneButton = fragmentView.findViewById(R.id.one);
if (oneButton != null) {
diff --git a/src/com/android/contacts/dialpad/UnicodeDialerKeyListener.java b/src/com/android/contacts/dialpad/UnicodeDialerKeyListener.java
new file mode 100644
index 0000000..faddcea
--- /dev/null
+++ b/src/com/android/contacts/dialpad/UnicodeDialerKeyListener.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.dialpad;
+
+import android.telephony.PhoneNumberUtils;
+import android.text.Spanned;
+import android.text.method.DialerKeyListener;
+
+/**
+ * {@link DialerKeyListener} with Unicode support. Converts any Unicode(e.g. Arabic) characters
+ * that represent digits into digits before filtering the results so that we can support
+ * pasted digits from Unicode languages.
+ */
+public class UnicodeDialerKeyListener extends DialerKeyListener {
+ public static final UnicodeDialerKeyListener INSTANCE = new UnicodeDialerKeyListener();
+
+ @Override
+ public CharSequence filter(CharSequence source, int start, int end,
+ Spanned dest, int dstart, int dend) {
+ CharSequence converted = PhoneNumberUtils.replaceUnicodeDigits(source.toString());
+ // PhoneNumberUtils.replaceUnicodeDigits performs a character for character replacement,
+ // so we can assume that start and end positions should remain unchanged.
+ CharSequence result = super.filter(converted, start, end, dest, dstart, dend);
+ if (result == null) {
+ if (source.equals(converted)) {
+ // There was no conversion or filtering performed. Just return null according to
+ // the behavior of DialerKeyListener.
+ return null;
+ } else {
+ // filter returns null if the charsequence is to be returned unchanged/unfiltered.
+ // But in this case we do want to return a modified character string (even if
+ // none of the characters in the modified string are filtered). So if
+ // result == null we return the unfiltered but converted numeric string instead.
+ return converted.subSequence(start, end);
+ }
+ }
+ return result;
+ }
+}
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index e29e488..028c01f 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -118,9 +118,6 @@
private static final String KEY_IS_USER_PROFILE = "isUserProfile";
private static final String KEY_UPDATED_PHOTOS = "updatedPhotos";
- private static final String[] VALID_ACTIONS = {Intent.ACTION_EDIT, Intent.ACTION_INSERT,
- ContactEditorActivity.ACTION_SAVE_COMPLETED};
-
public static final String SAVE_MODE_EXTRA_KEY = "saveMode";
@@ -405,13 +402,13 @@
* @throws IllegalArgumentException when the action is invalid.
*/
private void validateAction(String action) {
- for (String validAction : VALID_ACTIONS) {
- if (validAction.equals(action)) {
- return;
- }
+ if (Intent.ACTION_EDIT.equals(action) || Intent.ACTION_INSERT.equals(action) ||
+ ContactEditorActivity.ACTION_SAVE_COMPLETED.equals(action)) {
+ return;
}
throw new IllegalArgumentException("Unknown Action String " + mAction +
- ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT);
+ ". Only support " + Intent.ACTION_EDIT + " or " + Intent.ACTION_INSERT + " or " +
+ ContactEditorActivity.ACTION_SAVE_COMPLETED);
}
@Override
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index 6294b40..e0dce8c 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -155,6 +155,7 @@
R.id.group_source_view_container);
mEmptyView = mRootView.findViewById(android.R.id.empty);
mMemberListView = (ListView) mRootView.findViewById(android.R.id.list);
+ mMemberListView.setItemsCanFocus(true);
mMemberListView.setAdapter(mAdapter);
return mRootView;
diff --git a/src/com/android/contacts/model/dataitem/DataItem.java b/src/com/android/contacts/model/dataitem/DataItem.java
index 25c44cb..391c657 100644
--- a/src/com/android/contacts/model/dataitem/DataItem.java
+++ b/src/com/android/contacts/model/dataitem/DataItem.java
@@ -206,6 +206,17 @@
return actionBody == null ? null : actionBody.toString();
}
+ /**
+ * This builds the data string(intended for display) depending on the type of data item. It
+ * returns the same value as {@link #buildDataString} by default, but certain data items can
+ * override it to provide their version of formatted data strings.
+ *
+ * @return Data string representing the data item, possibly formatted for display
+ */
+ public String buildDataStringForDisplay() {
+ return buildDataString();
+ }
+
public String getKindString() {
final DataKind kind = getDataKind();
return (kind.titleRes == -1 || kind.titleRes == 0) ? ""
diff --git a/src/com/android/contacts/model/dataitem/PhoneDataItem.java b/src/com/android/contacts/model/dataitem/PhoneDataItem.java
index 61d62c1..3931563 100644
--- a/src/com/android/contacts/model/dataitem/PhoneDataItem.java
+++ b/src/com/android/contacts/model/dataitem/PhoneDataItem.java
@@ -70,4 +70,17 @@
}
}
+ /**
+ * Returns the formatted phone number (if already computed using {@link
+ * #computeFormattedPhoneNumber}). Otherwise this method returns the unformatted phone number.
+ */
+ @Override
+ public String buildDataStringForDisplay() {
+ final String formatted = getFormattedPhoneNumber();
+ if (formatted != null) {
+ return formatted;
+ } else {
+ return getNumber();
+ }
+ }
}
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index c10c338..829475f 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -95,7 +95,7 @@
}
mIsPrimary = item.isSuperPrimary();
- mBody = item.buildDataString();
+ mBody = item.buildDataStringForDisplay();
mDataId = item.getId();
mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, mDataId);
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index 16814dc..d39b380 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -546,7 +546,10 @@
if (mLookupUri == null) {
Log.wtf(TAG, "Lookup uri wasn't initialized. Loader was started too early");
}
- return new ContactLoader(getApplicationContext(), mLookupUri, false);
+ return new ContactLoader(getApplicationContext(), mLookupUri,
+ false /*loadGroupMetaData*/, false /*loadStreamItems*/,
+ false /*loadInvitableAccountTypes*/, false /*postViewNotification*/,
+ true /*computeFormattedPhoneNumber*/);
}
};
@@ -587,13 +590,18 @@
final CheckableImageView actionView = getActionViewAt(position);
mTrackScroller.requestChildRectangleOnScreen(actionView,
new Rect(0, 0, actionView.getWidth(), actionView.getHeight()), false);
+ renderSelectedRectangle(position, 0);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ renderSelectedRectangle(position, positionOffset);
+ }
+
+ private void renderSelectedRectangle(int position, float positionOffset) {
final RelativeLayout.LayoutParams layoutParams =
(RelativeLayout.LayoutParams) mSelectedTabRectangle.getLayoutParams();
- final int width = mSelectedTabRectangle.getWidth();
+ final int width = layoutParams.width;
layoutParams.leftMargin = (int) ((position + positionOffset) * width);
mSelectedTabRectangle.setLayoutParams(layoutParams);
}
diff --git a/tests/src/com/android/contacts/dialpad/UnicodeDialerKeyListenerTest.java b/tests/src/com/android/contacts/dialpad/UnicodeDialerKeyListenerTest.java
new file mode 100644
index 0000000..3dbe18c
--- /dev/null
+++ b/tests/src/com/android/contacts/dialpad/UnicodeDialerKeyListenerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.contacts.dialpad;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.contacts.dialpad.UnicodeDialerKeyListener;
+
+import junit.framework.TestCase;
+/**
+ * Test case for {@link UnicodeDialerKeyListener}.
+ *
+ * adb shell am instrument -w -e class com.android.contacts.dialpad.UnicodeDialerKeyListenerTest \
+ com.android.contacts.tests/android.test.InstrumentationTestRunner
+ */
+@SmallTest
+public class UnicodeDialerKeyListenerTest extends TestCase {
+ private static UnicodeDialerKeyListener mUnicodeDialerKeyListener;
+
+ // Pasted numeric digits should remain unchanged
+ public void testNumericDigits() {
+ // The last 3 arguments don't matter because {@link NumberKeyListener} doesn't care
+ // about dest, dstart, dend in
+ // public CharSequence filter (CharSequence source, int start, int end,
+ // Spanned dest, int dstart, int dend)
+ // anyway. This applies to all tests.
+ assertEquals(null, mUnicodeDialerKeyListener.filter("111222333", 0, 9, null, 0, 0));
+ }
+
+ // Pasted Arabic digits should be converted to ascii digits
+ public void testArabicDigits() {
+ assertEquals("0123456789", mUnicodeDialerKeyListener.filter("٠١٢٣٤٥٦٧٨٩", 0, 10,
+ null, 0, 0));
+ }
+
+ // Pasted Farsi(Persian) digits should be converted to ascii digits
+ // Note the difference in digits 4, 5 and 6 when compared to arabic. The rest of the digits
+ // look the same compared to the Arabic digits but they actually have different unicode codes.
+ public void testFarsiDigits() {
+ assertEquals("0123456789", mUnicodeDialerKeyListener.filter("۰۱۲۳۴۵۶۷۸۹", 0, 10,
+ null, 0, 0));
+ }
+
+ // This is a rare use case but we should make sure it works all the same.
+ public void testCombinationDigits() {
+ assertEquals("15102849177", mUnicodeDialerKeyListener.filter("۱510٢٨٤۹۱۷۷", 0, 11,
+ null, 0, 0));
+ }
+
+ // Test that a normal digit string with dashes is returned unfiltered
+ public void testDashes() {
+ assertEquals(null, mUnicodeDialerKeyListener.filter("1510-284-9177", 0, 13,
+ null, 0, 0));
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ mUnicodeDialerKeyListener = UnicodeDialerKeyListener.INSTANCE;
+ }
+}