Merge "Launch viewStreamItemPhotoActivity when photo is tapped..."
diff --git a/res/layout/contact_tile_list.xml b/res/layout/contact_tile_list.xml
index 2047b13..1df1377 100644
--- a/res/layout/contact_tile_list.xml
+++ b/res/layout/contact_tile_list.xml
@@ -32,6 +32,7 @@
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:layout_marginTop="@dimen/empty_message_top_margin"
- android:textAppearance="?android:attr/textAppearanceMedium"/>
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="?android:attr/textAppearanceLarge"/>
</FrameLayout>
diff --git a/res/layout/contacts_unavailable_fragment.xml b/res/layout/contacts_unavailable_fragment.xml
index 5566589..1abc020 100644
--- a/res/layout/contacts_unavailable_fragment.xml
+++ b/res/layout/contacts_unavailable_fragment.xml
@@ -14,70 +14,81 @@
limitations under the License.
-->
-<com.android.contacts.widget.InterpolatingLayout
+<ScrollView
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="match_parent"
- android:background="@drawable/panel_message">
-
+ android:fillViewport="true">
<LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
android:orientation="vertical"
- ex:layout_narrowParentWidth="600dip"
- ex:layout_narrowWidth="400dip"
- ex:layout_wideParentWidth="880dip"
- ex:layout_wideWidth="600dip">
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:background="@drawable/panel_message">
<TextView
android:id="@+id/message"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_marginBottom="20dip" />
-
- <Button
- android:id="@+id/create_contact_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dip"
- android:text="@string/contacts_unavailable_create_contact" />
-
- <Button
- android:id="@+id/add_account_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dip"
- android:text="@string/contacts_unavailable_add_account" />
-
- <Button
- android:id="@+id/import_contacts_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dip"
- android:text="@string/contacts_unavailable_import_contacts" />
-
- <Button
- android:id="@+id/import_failure_uninstall_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dip"
- android:text="@string/upgrade_out_of_memory_uninstall" />
-
- <Button
- android:id="@+id/import_failure_retry_button"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="15dip"
- android:text="@string/upgrade_out_of_memory_retry" />
-
- <ProgressBar
- android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginTop="48dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <TextView
+ android:id="@+id/secondary_message"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
android:layout_gravity="center_horizontal"
- android:layout_marginBottom="15dip" />
+ android:layout_marginBottom="@dimen/no_accounts_message_margin" />
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_marginLeft="48dip"
+ android:layout_marginRight="48dip"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+ <Button
+ android:id="@+id/create_contact_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dip"
+ android:text="@string/contacts_unavailable_create_contact" />
+
+ <Button
+ android:id="@+id/add_account_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dip"
+ android:text="@string/contacts_unavailable_add_account" />
+
+ <Button
+ android:id="@+id/import_contacts_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dip"
+ android:text="@string/contacts_unavailable_import_contacts" />
+
+ <Button
+ android:id="@+id/import_failure_uninstall_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dip"
+ android:text="@string/upgrade_out_of_memory_uninstall" />
+
+ <Button
+ android:id="@+id/import_failure_retry_button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="15dip"
+ android:text="@string/upgrade_out_of_memory_retry" />
+
+ <ProgressBar
+ android:id="@+id/progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="15dip" />
+ </LinearLayout>
</LinearLayout>
-</com.android.contacts.widget.InterpolatingLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/res/layout/dialpad_fragment.xml b/res/layout/dialpad_fragment.xml
index 9c5099f..75d5938 100644
--- a/res/layout/dialpad_fragment.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -25,6 +25,7 @@
<!-- Text field and possibly soft menu button above the keypad where
the digits are displayed. -->
<RelativeLayout
+ android:id="@+id/digits_container"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="0.200"
diff --git a/res/layout/group_browse_list_fragment.xml b/res/layout/group_browse_list_fragment.xml
index 6e82e8f..e3d98f0 100644
--- a/res/layout/group_browse_list_fragment.xml
+++ b/res/layout/group_browse_list_fragment.xml
@@ -38,32 +38,31 @@
android:layout_marginTop="@dimen/empty_message_top_margin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingTop="8dip"
android:gravity="center_horizontal"
- android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="?android:attr/textColorSecondary"
android:text="@string/noGroups" />
<LinearLayout
android:id="@+id/add_accounts"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
android:orientation="vertical">
<TextView
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
- android:layout_marginTop="@dimen/no_accounts_message_margin"
android:layout_marginBottom="@dimen/no_accounts_message_margin"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
android:text="@string/noAccounts" />
<Button
android:id="@+id/add_account_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/add_account_button_left_margin"
- android:layout_marginRight="@dimen/add_account_button_right_margin"
android:gravity="center"
android:layout_gravity="center_horizontal"
android:textAppearance="?android:attr/textAppearanceMedium"
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
index 599cc13..6bac5ea 100644
--- a/res/layout/group_browse_list_item.xml
+++ b/res/layout/group_browse_list_item.xml
@@ -69,38 +69,6 @@
android:singleLine="true" />
</LinearLayout>
-
- <TableLayout
- android:id="@+id/icons"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true">
- <TableRow
- android:layout_marginBottom="1dip">
- <ImageView
- android:id="@+id/icon_1"
- android:layout_width="@dimen/group_list_icon_size"
- android:layout_height="@dimen/group_list_icon_size"
- android:layout_marginRight="1dip" />
- <ImageView
- android:id="@+id/icon_2"
- android:layout_width="@dimen/group_list_icon_size"
- android:layout_height="@dimen/group_list_icon_size" />
- </TableRow>
- <TableRow>
- <ImageView
- android:id="@+id/icon_3"
- android:layout_width="@dimen/group_list_icon_size"
- android:layout_height="@dimen/group_list_icon_size"
- android:layout_marginRight="1dip" />
- <ImageView
- android:id="@+id/icon_4"
- android:layout_width="@dimen/group_list_icon_size"
- android:layout_height="@dimen/group_list_icon_size" />
- </TableRow>
-
- </TableLayout>
</RelativeLayout>
</LinearLayout>
diff --git a/res/menu/dialtacts_options.xml b/res/menu/dialtacts_options.xml
index cc9543a..2c83f6b 100644
--- a/res/menu/dialtacts_options.xml
+++ b/res/menu/dialtacts_options.xml
@@ -29,4 +29,9 @@
android:id="@+id/filter_option"
android:title="@string/menu_contacts_filter"
android:showAsAction="withText" />
+
+ <item
+ android:id="@+id/add_contact"
+ android:title="@string/menu_newContact"
+ android:showAsAction="withText" />
</menu>
diff --git a/res/menu/dialtacts_search_options.xml b/res/menu/dialtacts_search_options.xml
index f2e0c67..0979ebb 100644
--- a/res/menu/dialtacts_search_options.xml
+++ b/res/menu/dialtacts_search_options.xml
@@ -19,4 +19,8 @@
android:id="@+id/filter_option"
android:title="@string/menu_contacts_filter"
android:showAsAction="withText" />
+ <item
+ android:id="@+id/add_contact"
+ android:title="@string/menu_newContact"
+ android:showAsAction="withText" />
</menu>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a67aa6b..f5fd3bf 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -240,10 +240,8 @@
<dimen name="call_detail_action_bar_height">60dip</dimen>
<!-- Empty message margins -->
- <dimen name="empty_message_top_margin">43dip</dimen>
- <dimen name="no_accounts_message_margin">15dip</dimen>
- <dimen name="add_account_button_left_margin">50dip</dimen>
- <dimen name="add_account_button_right_margin">50dip</dimen>
+ <dimen name="empty_message_top_margin">48dip</dimen>
+ <dimen name="no_accounts_message_margin">20dip</dimen>
<!-- For contact filter setting screens -->
<dimen name="contact_filter_left_margin">16dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c7a2bc7..11e7e38 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -783,16 +783,16 @@
<string name="searching_vcard_message" product="default">Searching for vCard data on SD card</string>
<!-- Dialog title shown when scanning VCard data failed. [CHAR LIMIT=NONE] -->
- <string name="scanning_sdcard_failed_title" product="nosdcard">Scanning storage failed</string>
+ <string name="scanning_sdcard_failed_title" product="nosdcard">Couldn\'t scan storage</string>
<!-- Dialog title shown when scanning VCard data failed. -->
- <string name="scanning_sdcard_failed_title" product="default">Scanning SD card failed</string>
+ <string name="scanning_sdcard_failed_title" product="default">Couldn\'t scan SD card</string>
<!-- Dialog message shown when searching VCard data failed.
An exact reason for the failure should [CHAR LIMIT=NONE] -->
- <string name="scanning_sdcard_failed_message" product="nosdcard">Scanning storage failed (Reason: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="scanning_sdcard_failed_message" product="nosdcard">Couldn\'t scan storage (Reason: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
<!-- Dialog message shown when searching VCard data failed.
An exact reason for the failure should -->
- <string name="scanning_sdcard_failed_message" product="default">Scanning SD card failed (Reason: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="scanning_sdcard_failed_message" product="default">Couldn\'t scan SD card (Reason: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
<!-- The failed reason shown when Contacts app (especially vCard importer/exporter)
emitted some I/O error. Exact reason will be appended by the system. -->
@@ -805,14 +805,14 @@
<!-- The failed reason shown when vCard parser was not able to be parsed by the current vCard
implementation. This might happen even when the input vCard is completely valid, though
we believe it is rather rare in the actual world. -->
- <string name="fail_reason_vcard_parse_error">Failed to parse vCard for unexpected reason</string>
+ <string name="fail_reason_vcard_parse_error">Couldn\'t parse vCard for unexpected reason</string>
<!-- The failed reason shown when vCard importer doesn't support the format.
This may be shown when the vCard is corrupted [CHAR LIMIT=40] -->
<string name="fail_reason_not_supported">The format is not supported.</string>
<!-- Message used when vCard import has failed. [CHAR LIMIT=40] -->
- <string name="vcard_import_failed">Failed to import vCard</string>
+ <string name="vcard_import_failed">Couldn\'t import vCard</string>
<!-- The failure message shown when the system could not find any vCard file.
(with extension ".vcf" in (USB) storage.)
@@ -824,11 +824,11 @@
<string name="import_failure_no_vcard_file" product="default">No vCard file found on the SD card</string>
<!-- Fail reason shown when vCard importer failed to look over meta information stored in vCard file(s). -->
- <string name="fail_reason_failed_to_collect_vcard_meta_info">Failed to collect meta information of given vCard file(s).</string>
+ <string name="fail_reason_failed_to_collect_vcard_meta_info">Couldn\'t collect meta information of given vCard file(s).</string>
<!-- The failed reason shown when the import of some of vCard files failed during multiple vCard
files import. It includes the case where all files were failed to be imported. -->
- <string name="fail_reason_failed_to_read_files">One or more files failed to be imported (%s).</string>
+ <string name="fail_reason_failed_to_read_files">One or more files couldn\'t be imported (%s).</string>
<!-- The failed reason which should not be shown but it may in some buggy condition. -->
<string name="fail_reason_unknown">Unknown error</string>
@@ -857,7 +857,7 @@
<string name="importing_vcard_description">Importing <xliff:g id="name" example="Joe Due">%s</xliff:g></string>
<!-- Dialog title shown when reading vCard data failed [CHAR LIMIT=40] -->
- <string name="reading_vcard_failed_title">Failed to Read vCard data</string>
+ <string name="reading_vcard_failed_title">Couldn\'t read vCard data</string>
<!-- The title shown when reading vCard is canceled (probably by a user)
[CHAR LIMIT=40] -->
@@ -905,10 +905,10 @@
<string name="confirm_export_message">Export your contact list to file \"<xliff:g id="vcard_filename">%s</xliff:g>\"?</string>
<!-- Dialog title shown when exporting Contact data failed -->
- <string name="exporting_contact_failed_title">Failed to export contact data</string>
+ <string name="exporting_contact_failed_title">Couldn\'t export contact data</string>
<!-- Dialog message shown when exporting Contact data failed -->
- <string name="exporting_contact_failed_message">Failed to export contact data.\nReason for failure: \"<xliff:g id="fail_reason">%s</xliff:g>\"</string>
+ <string name="exporting_contact_failed_message">Couldn\'t export contact data.\nReason: \"<xliff:g id="fail_reason">%s</xliff:g>\"</string>
<!-- The failed reason shown when there's no contact which is allowed to be exported.
Note that user may have contacts data but all of them are probably not allowed to be
@@ -951,7 +951,7 @@
<!-- The error reason the vCard composer "may" emit when database is corrupted or
something is going wrong. Usually users should not see this text. -->
- <string name="composer_failed_to_get_database_infomation">Failed to get database information</string>
+ <string name="composer_failed_to_get_database_infomation">Couldn\'t get database information</string>
<!-- This error message shown when the user actually have no contact
(e.g. just after data-wiping), or, data providers of the contact list prohibits their
@@ -991,7 +991,7 @@
<string name="cancel_export_confirmation_message">Are you sure to cancel exporting <xliff:g id="filename" example="export.vcf">%s</xliff:g>?</string>
<!-- Title shown in a Dialog telling users cancel vCard import/export operation is failed. [CHAR LIMIT=40] -->
- <string name="cancel_vcard_import_or_export_failed">Failed to cancel vCard import/export</string>
+ <string name="cancel_vcard_import_or_export_failed">Couldn\'t cancel vCard import/export</string>
<!-- The string used to describe Contacts as a searchable item within system search settings. -->
<string name="search_settings_description">Names of your contacts</string>
@@ -1630,16 +1630,16 @@
<string name="notification_new_voicemail_ticker">New voicemail from <xliff:g id="caller">%1$s</xliff:g></string>
<!-- Message to show when there is an error playing back the voicemail. [CHAR LIMIT=40] -->
- <string name="voicemail_playback_error">failed to play voicemail</string>
+ <string name="voicemail_playback_error">Couldn\'t play voicemail.</string>
<!-- Message to display before we have prepared the media player, i.e. before we know duration. [CHAR LIMIT=40] -->
- <string name="voicemail_buffering">buffering...</string>
+ <string name="voicemail_buffering">Buffering\u2026</string>
<!-- Message to display whilst we are waiting for the content to be fetched. [CHAR LIMIT=40] -->
- <string name="voicemail_fetching_content">fetching voicemail...</string>
+ <string name="voicemail_fetching_content">Fetching voicemail\u2026</string>
<!-- Message to display if we fail to get content within a suitable time period. [CHAR LIMIT=40] -->
- <string name="voicemail_fetching_timout">failed to fetch voicemail</string>
+ <string name="voicemail_fetching_timout">Couldn\'t fetch voicemail.</string>
<!-- The header in the call log used to identify missed calls and voicemail that have not yet been consumed [CHAR LIMIT=10] -->
<string name="call_log_new_header">New</string>
diff --git a/src/com/android/contacts/ContactsUtils.java b/src/com/android/contacts/ContactsUtils.java
index 45ce4fe..2f13481 100644
--- a/src/com/android/contacts/ContactsUtils.java
+++ b/src/com/android/contacts/ContactsUtils.java
@@ -16,6 +16,8 @@
package com.android.contacts;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.AccountWithDataSet;
import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.PhoneNumberUtil.MatchType;
@@ -29,6 +31,8 @@
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
+import java.util.List;
+
public class ContactsUtils {
private static final String TAG = "ContactsUtils";
private static final String WAIT_SYMBOL_AS_STRING = String.valueOf(PhoneNumberUtils.WAIT);
@@ -166,4 +170,12 @@
(CountryDetector) context.getSystemService(Context.COUNTRY_DETECTOR);
return detector.detectCountry().getCountryIso();
}
+
+ public static boolean areAccountsAvailable(Context context) {
+ final List<AccountWithDataSet> accounts =
+ AccountTypeManager.getInstance(context).getAccounts(true /* writeable */);
+ return !accounts.isEmpty();
+ }
+
+
}
diff --git a/src/com/android/contacts/activities/ContactEditorActivity.java b/src/com/android/contacts/activities/ContactEditorActivity.java
index 2936110..c69cc04 100644
--- a/src/com/android/contacts/activities/ContactEditorActivity.java
+++ b/src/com/android/contacts/activities/ContactEditorActivity.java
@@ -151,11 +151,6 @@
public void onSaveFinished(Intent resultIntent) {
if (resultIntent != null) {
startActivity(resultIntent);
- } else {
- // Navigate home
- Intent intent = new Intent(ContactEditorActivity.this, PeopleActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
}
finish();
}
diff --git a/src/com/android/contacts/activities/DialtactsActivity.java b/src/com/android/contacts/activities/DialtactsActivity.java
index 12709c8..048ae5f 100644
--- a/src/com/android/contacts/activities/DialtactsActivity.java
+++ b/src/com/android/contacts/activities/DialtactsActivity.java
@@ -46,6 +46,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.CallLog.Calls;
+import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents.UI;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
@@ -253,6 +254,9 @@
popupMenu.inflate(R.menu.dialtacts_search_options);
final MenuItem filterOptionMenuItem = menu.findItem(R.id.filter_option);
filterOptionMenuItem.setOnMenuItemClickListener(mFilterOptionsMenuItemClickListener);
+ final MenuItem addContactOptionMenuItem = menu.findItem(R.id.add_contact);
+ addContactOptionMenuItem.setIntent(
+ new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI));
popupMenu.show();
}
};
@@ -693,6 +697,7 @@
public boolean onPrepareOptionsMenu(Menu menu) {
final MenuItem searchMenuItem = menu.findItem(R.id.search_on_action_bar);
final MenuItem filterOptionMenuItem = menu.findItem(R.id.filter_option);
+ final MenuItem addContactOptionMenuItem = menu.findItem(R.id.add_contact);
final MenuItem callSettingsMenuItem = menu.findItem(R.id.menu_call_settings);
Tab tab = getActionBar().getSelectedTab();
if (mInSearchUi) {
@@ -701,9 +706,13 @@
filterOptionMenuItem.setVisible(true);
filterOptionMenuItem.setOnMenuItemClickListener(
mFilterOptionsMenuItemClickListener);
+ addContactOptionMenuItem.setVisible(true);
+ addContactOptionMenuItem.setIntent(
+ new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI));
} else {
// Filter option menu should be not be shown as a overflow menu.
filterOptionMenuItem.setVisible(false);
+ addContactOptionMenuItem.setVisible(false);
}
callSettingsMenuItem.setVisible(false);
} else {
@@ -719,6 +728,7 @@
showCallSettingsMenu = true;
}
filterOptionMenuItem.setVisible(false);
+ addContactOptionMenuItem.setVisible(false);
if (showCallSettingsMenu) {
callSettingsMenuItem.setVisible(true);
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 68e9cbb..1c69ef9 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -19,6 +19,7 @@
import com.android.contacts.ContactLoader;
import com.android.contacts.ContactSaveService;
import com.android.contacts.ContactsActivity;
+import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
import com.android.contacts.activities.ActionBarAdapter.TabState;
import com.android.contacts.detail.ContactDetailFragment;
@@ -199,9 +200,7 @@
}
private boolean areAccountsAvailable() {
- final List<AccountWithDataSet> accounts =
- AccountTypeManager.getInstance(this).getAccounts(true /* writeable */);
- return !accounts.isEmpty();
+ return ContactsUtils.areAccountsAvailable(this);
}
@@ -681,13 +680,14 @@
switch (tab) {
case FAVORITES:
mContactsUnavailableFragment.setMessageText(
- R.string.listTotalAllContactsZeroStarred);
+ R.string.listTotalAllContactsZeroStarred, -1);
break;
case GROUPS:
- mContactsUnavailableFragment.setMessageText(R.string.noGroups);
+ mContactsUnavailableFragment.setMessageText(R.string.noGroups,
+ areAccountsAvailable() ? -1 : R.string.noAccounts);
break;
case ALL:
- mContactsUnavailableFragment.setMessageText(R.string.noContacts);
+ mContactsUnavailableFragment.setMessageText(R.string.noContacts, -1);
break;
}
}
diff --git a/src/com/android/contacts/dialpad/DialpadFragment.java b/src/com/android/contacts/dialpad/DialpadFragment.java
index 188c546..eef5a61 100644
--- a/src/com/android/contacts/dialpad/DialpadFragment.java
+++ b/src/com/android/contacts/dialpad/DialpadFragment.java
@@ -96,7 +96,9 @@
public void onSearchButtonPressed();
}
+ private View mDigitsContainer;
private EditText mDigits;
+
private View mDelete;
private ToneGenerator mToneGenerator;
private Object mToneGeneratorLock = new Object();
@@ -172,34 +174,42 @@
};
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
- /**
- * Listen for phone state changes so that we can take down the
- * "dialpad chooser" if the phone becomes idle while the
- * chooser UI is visible.
- */
- @Override
- public void onCallStateChanged(int state, String incomingNumber) {
- // Log.i(TAG, "PhoneStateListener.onCallStateChanged: "
- // + state + ", '" + incomingNumber + "'");
- if ((state == TelephonyManager.CALL_STATE_IDLE) && dialpadChooserVisible()) {
- // Log.i(TAG, "Call ended with dialpad chooser visible! Taking it down...");
- // Note there's a race condition in the UI here: the
- // dialpad chooser could conceivably disappear (on its
- // own) at the exact moment the user was trying to select
- // one of the choices, which would be confusing. (But at
- // least that's better than leaving the dialpad chooser
- // onscreen, but useless...)
- showDialpadChooser(false);
- }
+ /**
+ * Listen for phone state changes so that we can take down the
+ * "dialpad chooser" if the phone becomes idle while the
+ * chooser UI is visible.
+ */
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ // Log.i(TAG, "PhoneStateListener.onCallStateChanged: "
+ // + state + ", '" + incomingNumber + "'");
+ if ((state == TelephonyManager.CALL_STATE_IDLE) && dialpadChooserVisible()) {
+ // Log.i(TAG, "Call ended with dialpad chooser visible! Taking it down...");
+ // Note there's a race condition in the UI here: the
+ // dialpad chooser could conceivably disappear (on its
+ // own) at the exact moment the user was trying to select
+ // one of the choices, which would be confusing. (But at
+ // least that's better than leaving the dialpad chooser
+ // onscreen, but useless...)
+ showDialpadChooser(false);
}
- };
+ }
+ };
+
+ private boolean mWasEmptyBeforeTextChange;
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // Do nothing
+ mWasEmptyBeforeTextChange = TextUtils.isEmpty(s);
}
public void onTextChanged(CharSequence input, int start, int before, int changeCount) {
- // Do nothing
+ if (mWasEmptyBeforeTextChange != TextUtils.isEmpty(input)) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.invalidateOptionsMenu();
+ }
+ }
+
// DTMF Tones do not need to be played here any longer -
// the DTMF dialer handles that functionality now.
}
@@ -240,6 +250,7 @@
// Load up the resources for the text field.
Resources r = getResources();
+ mDigitsContainer = fragmentView.findViewById(R.id.digits_container);
mDigits = (EditText) fragmentView.findViewById(R.id.digits);
mDigits.setKeyListener(DialerKeyListener.getInstance());
mDigits.setOnClickListener(this);
@@ -920,7 +931,7 @@
if (enabled) {
// Log.i(TAG, "Showing dialpad chooser!");
- mDigits.setVisibility(View.GONE);
+ mDigitsContainer.setVisibility(View.GONE);
if (mDialpad != null) mDialpad.setVisibility(View.GONE);
mAdditionalButtonsRow.setVisibility(View.GONE);
mDialpadChooser.setVisibility(View.VISIBLE);
@@ -933,7 +944,7 @@
mDialpadChooser.setAdapter(mDialpadChooserAdapter);
} else {
// Log.i(TAG, "Displaying normal Dialer UI.");
- mDigits.setVisibility(View.VISIBLE);
+ mDigitsContainer.setVisibility(View.VISIBLE);
if (mDialpad != null) mDialpad.setVisibility(View.VISIBLE);
mAdditionalButtonsRow.setVisibility(View.VISIBLE);
mDialpadChooser.setVisibility(View.GONE);
diff --git a/src/com/android/contacts/group/GroupBrowseListAdapter.java b/src/com/android/contacts/group/GroupBrowseListAdapter.java
index c8c16e6..63a5d2c 100644
--- a/src/com/android/contacts/group/GroupBrowseListAdapter.java
+++ b/src/com/android/contacts/group/GroupBrowseListAdapter.java
@@ -23,155 +23,26 @@
import com.android.contacts.model.AccountTypeManager;
import com.android.internal.util.Objects;
-import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
-import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Groups;
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.ArrayList;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* Adapter to populate the list of groups.
*/
public class GroupBrowseListAdapter extends BaseAdapter {
- private static final int MAX_ICONS_PER_GROUP_ROW = 4;
-
- private static final String[] PROJECTION_GROUP_MEMBERSHIP_INFO = new String[] {
- GroupMembership._ID,
- GroupMembership.PHOTO_ID
- };
- private static final int GROUP_MEMBERSHIP_COLUMN_PHOTO_ID = 1;
-
- /**
- * Arguments for asynchronous photo ID loading. See {@link AsyncPhotoIdLoadTask}
- */
- private static class AsyncPhotoIdLoadArg {
- public final View icons;
- public final long groupId;
- public final Map<Long, ArrayList<Long>> groupPhotoIdMap;
- public final ContentResolver contentResolver;
- public final ContactPhotoManager contactPhotoManager;
-
- public AsyncPhotoIdLoadArg(
- View icons, long groupId, Map<Long, ArrayList<Long>> groupPhotoIdMap,
- ContentResolver contentResolver, ContactPhotoManager contactPhotoManager) {
- this.icons = icons;
- this.groupId = groupId;
- this.groupPhotoIdMap = groupPhotoIdMap;
- this.contentResolver = contentResolver;
- this.contactPhotoManager = contactPhotoManager;
- }
- }
-
- /**
- * Loads photo IDs associated with a group ID supplied from {@link AsyncPhotoIdLoadArg#groupId},
- * storing them in {@link GroupBrowseListAdapter#mGroupPhotoIdMap}.
- *
- * This AsyncTask also remembers a View which is associated with the group ID at the moment it
- * is initiated (we use {@link View#setTag(Object) and View#getTag() to associate them}. If the
- * View is still associated with the group ID after the asynchronous photo ID load, this class
- * also asks {@link ContactPhotoManager} to load actual photo contents. Its parent (typically
- * ListView) may reuse Views for different group IDs, so the photo content load often don't
- * occur.
- */
- private static class AsyncPhotoIdLoadTask extends
- AsyncTask<AsyncPhotoIdLoadArg, Void, ArrayList<Long>> {
-
- private View mIcons;
- private long mGroupId;
- private Map<Long, ArrayList<Long>> mGroupPhotoIdMap;
- private ContentResolver mContentResolver;
- private ContactPhotoManager mContactPhotoManager;
-
- @Override
- protected ArrayList<Long> doInBackground(AsyncPhotoIdLoadArg... params) {
- final AsyncPhotoIdLoadArg arg = params[0];
- mIcons = arg.icons;
- mGroupId = arg.groupId;
- mGroupPhotoIdMap = arg.groupPhotoIdMap;
- mContentResolver = arg.contentResolver;
- mContactPhotoManager = arg.contactPhotoManager;
-
- // Multiple requests for one group ID is possible. We just ignore duplicates,
- // assuming query results won't change.
- if (mGroupPhotoIdMap.containsKey(mGroupId)) {
- return null;
- }
-
- final ArrayList<Long> photoIds = new ArrayList<Long>(MAX_ICONS_PER_GROUP_ROW);
- Cursor cursor = null;
- try {
- cursor = mContentResolver.query(Data.CONTENT_URI,
- PROJECTION_GROUP_MEMBERSHIP_INFO,
- GroupMembership.MIMETYPE + "=? AND "
- + GroupMembership.PHOTO_ID + " IS NOT NULL AND "
- + GroupMembership.GROUP_ROW_ID + "=?",
- new String[] { GroupMembership.CONTENT_ITEM_TYPE,
- String.valueOf(mGroupId) }, null);
- if (cursor != null) {
- int count = 0;
- while (cursor.moveToNext() && count < MAX_ICONS_PER_GROUP_ROW) {
- photoIds.add(cursor.getLong(GROUP_MEMBERSHIP_COLUMN_PHOTO_ID));
- count++;
- }
- }
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- return photoIds;
- }
-
- @Override
- protected void onPostExecute(ArrayList<Long> photoIds) {
- if (photoIds == null) {
- return;
- }
-
- mGroupPhotoIdMap.put(mGroupId, photoIds);
-
- final View icons = mIcons;
- // If the original group ID, which was supplied when this AsyncTask was executed, is
- // consistent with the ID inside mArgs, it means the View isn't reused by the
- // other groups, and thus we can assume these Views are available for the group ID.
- final Long currentGroupId = (Long) icons.getTag();
- if (currentGroupId == mGroupId) {
- final ImageView[] children = getIconViewsSordedByFillOrder(icons);
- for (int i = 0; i < children.length; i++) {
- if (i < photoIds.size()) {
- mContactPhotoManager.loadPhoto(children[i], photoIds.get(i));
- } else {
- mContactPhotoManager.removePhoto(children[i]);
- }
- }
- }
- }
- }
-
private final Context mContext;
private final LayoutInflater mLayoutInflater;
private final AccountTypeManager mAccountTypeManager;
- private final Map<Long, ArrayList<Long>> mGroupPhotoIdMap =
- new ConcurrentHashMap<Long, ArrayList<Long>>();
-
- private final ContactPhotoManager mContactPhotoManager;
-
private Cursor mCursor;
private boolean mSelectionVisible;
@@ -181,7 +52,6 @@
mContext = context;
mLayoutInflater = LayoutInflater.from(context);
mAccountTypeManager = AccountTypeManager.getInstance(mContext);
- mContactPhotoManager = ContactPhotoManager.getInstance(mContext);
}
public void setCursor(Cursor cursor) {
@@ -308,35 +178,6 @@
viewCache.groupTitle.setText(entry.getTitle());
viewCache.groupMemberCount.setText(memberCountString);
- final View icons = result.findViewById(R.id.icons);
- final ImageView[] children = getIconViewsSordedByFillOrder(icons);
- final ArrayList<Long> photoIds = mGroupPhotoIdMap.get(entry.getGroupId());
-
- // Let the icon holder remember its associated group ID.
- // Each AsyncTask loading photo IDs will compare this ID with the AsyncTask's argument, and
- // check if the bound View is reused by the other list items or not. If the View is reused,
- // the group ID set here will be overridden by the new owner, thus ID inconsistency happens.
- icons.setTag(entry.getGroupId());
- if (photoIds != null) {
- // Cache is available. Let the photo manager load those IDs.
- for (int i = 0; i < children.length; i++) {
- if (i < photoIds.size()) {
- mContactPhotoManager.loadPhoto(children[i], photoIds.get(i));
- } else {
- mContactPhotoManager.removePhoto(children[i]);
- }
- }
- } else {
- // Cache is not available. Load photo IDs asynchronously.
- for (ImageView child : children) {
- mContactPhotoManager.removePhoto(child);
- }
- new AsyncPhotoIdLoadTask().execute(
- new AsyncPhotoIdLoadArg(icons, entry.getGroupId(),
- mGroupPhotoIdMap, mContext.getContentResolver(),
- mContactPhotoManager));
- }
-
if (mSelectionVisible) {
result.setActivated(isSelectedGroup(groupUri));
}
@@ -355,19 +196,6 @@
}
/**
- * Get ImageView objects inside the given View, sorted by the order photos should be filled.
- */
- private static ImageView[] getIconViewsSordedByFillOrder(View icons) {
- final ImageView[] children = new ImageView[] {
- (ImageView) icons.findViewById(R.id.icon_4),
- (ImageView) icons.findViewById(R.id.icon_2),
- (ImageView) icons.findViewById(R.id.icon_3),
- (ImageView) icons.findViewById(R.id.icon_1)
- };
- return children;
- }
-
- /**
* Cache of the children views of a contact detail entry represented by a
* {@link GroupListItem}
*/
diff --git a/src/com/android/contacts/group/GroupBrowseListFragment.java b/src/com/android/contacts/group/GroupBrowseListFragment.java
index aca638e..49835ef 100644
--- a/src/com/android/contacts/group/GroupBrowseListFragment.java
+++ b/src/com/android/contacts/group/GroupBrowseListFragment.java
@@ -16,6 +16,7 @@
package com.android.contacts.group;
+import com.android.contacts.ContactsUtils;
import com.android.contacts.GroupListLoader;
import com.android.contacts.R;
import com.android.contacts.group.GroupBrowseListAdapter.GroupListItemViewCache;
@@ -47,6 +48,7 @@
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
+import android.widget.TextView;
/**
* Fragment to display the list of groups.
@@ -81,7 +83,7 @@
private View mRootView;
private AutoScrollListView mListView;
- private View mEmptyView;
+ private TextView mEmptyView;
private View mAddAccountsView;
private View mAddAccountButton;
@@ -100,7 +102,7 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.group_browse_list_fragment, null);
- mEmptyView = mRootView.findViewById(R.id.empty);
+ mEmptyView = (TextView)mRootView.findViewById(R.id.empty);
mAdapter = new GroupBrowseListAdapter(mContext);
mAdapter.setSelectionVisible(mSelectionVisible);
@@ -120,7 +122,7 @@
}
});
- mEmptyView = mRootView.findViewById(R.id.empty);
+ mListView.setEmptyView(mEmptyView);
mAddAccountsView = mRootView.findViewById(R.id.add_accounts);
mAddAccountButton = mRootView.findViewById(R.id.add_account_button);
mAddAccountButton.setOnClickListener(new OnClickListener() {
@@ -133,7 +135,7 @@
startActivity(intent);
}
});
- setAddAccountsVisibility(false);
+ setAddAccountsVisibility(!ContactsUtils.areAccountsAvailable(mContext));
if (savedInstanceState != null) {
String groupUriString = savedInstanceState.getString(EXTRA_KEY_GROUP_URI);
@@ -193,6 +195,7 @@
@Override
public CursorLoader onCreateLoader(int id, Bundle args) {
+ mEmptyView.setText(null);
return new GroupListLoader(mContext);
}
@@ -207,6 +210,8 @@
};
private void bindGroupList() {
+ mEmptyView.setText(R.string.noGroups);
+ setAddAccountsVisibility(!ContactsUtils.areAccountsAvailable(mContext));
if (mGroupListCursor == null) {
return;
}
@@ -219,7 +224,6 @@
// Restore the scroll position.
mListView.onRestoreInstanceState(listState);
}
- mListView.setEmptyView(mEmptyView);
mSelectedGroupUri = mAdapter.getSelectedGroup();
if (mSelectionVisible && mSelectedGroupUri != null) {
diff --git a/src/com/android/contacts/list/ContactsUnavailableFragment.java b/src/com/android/contacts/list/ContactsUnavailableFragment.java
index 3bab3fd..74a578f 100644
--- a/src/com/android/contacts/list/ContactsUnavailableFragment.java
+++ b/src/com/android/contacts/list/ContactsUnavailableFragment.java
@@ -39,6 +39,7 @@
private View mView;
private TextView mMessageView;
+ private TextView mSecondaryMessageView;
private Button mCreateContactButton;
private Button mAddAccountButton;
private Button mImportContactsButton;
@@ -46,6 +47,7 @@
private Button mRetryUpgradeButton;
private ProgressBar mProgress;
private int mNoContactsMsgResId = -1;
+ private int mNSecNoContactsMsgResId = -1;
private OnContactsUnavailableActionListener mListener;
@@ -54,6 +56,7 @@
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView = inflater.inflate(R.layout.contacts_unavailable_fragment, null);
mMessageView = (TextView) mView.findViewById(R.id.message);
+ mSecondaryMessageView = (TextView) mView.findViewById(R.id.secondary_message);
mCreateContactButton = (Button) mView.findViewById(R.id.create_contact_button);
mCreateContactButton.setOnClickListener(this);
mAddAccountButton = (Button) mView.findViewById(R.id.add_account_button);
@@ -82,14 +85,7 @@
int providerStatus = mProviderStatusLoader.getProviderStatus();
switch (providerStatus) {
case ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS:
- if (mNoContactsMsgResId != -1) {
- mMessageView.setText(mNoContactsMsgResId);
- mMessageView.setGravity(Gravity.CENTER_HORIZONTAL);
- mMessageView.setVisibility(View.VISIBLE);
- } else {
- mMessageView.setGravity(Gravity.LEFT);
- mMessageView.setVisibility(View.GONE);
- }
+ setMessageText(mNoContactsMsgResId, mNSecNoContactsMsgResId);
mCreateContactButton.setVisibility(View.VISIBLE);
mAddAccountButton.setVisibility(View.VISIBLE);
mImportContactsButton.setVisibility(View.VISIBLE);
@@ -162,18 +158,31 @@
}
}
/**
- * Set the message to be shown if data is available for the selected tab
+ * Set the message to be shown if no data is available for the selected tab
*
- * @param resId - String resource ID of the message
+ * @param resId - String resource ID of the message , -1 means view will not be visible
*/
- public void setMessageText(int resId) {
+ public void setMessageText(int resId, int secResId) {
mNoContactsMsgResId = resId;
+ mNSecNoContactsMsgResId = secResId;
if (mMessageView != null &&
mProviderStatusLoader.getProviderStatus() ==
ProviderStatus.STATUS_NO_ACCOUNTS_NO_CONTACTS) {
- mMessageView.setText(mNoContactsMsgResId);
- mMessageView.setGravity(Gravity.CENTER_HORIZONTAL);
- mMessageView.setVisibility(View.VISIBLE);
+ if (resId != -1) {
+ mMessageView.setText(mNoContactsMsgResId);
+ mMessageView.setGravity(Gravity.CENTER_HORIZONTAL);
+ mMessageView.setVisibility(View.VISIBLE);
+ if (secResId != -1) {
+ mSecondaryMessageView.setText(mNSecNoContactsMsgResId);
+ mSecondaryMessageView.setGravity(Gravity.CENTER_HORIZONTAL);
+ mSecondaryMessageView.setVisibility(View.VISIBLE);
+ } else {
+ mSecondaryMessageView.setVisibility(View.INVISIBLE);
+ }
+ } else {
+ mSecondaryMessageView.setVisibility(View.GONE);
+ mMessageView.setVisibility(View.GONE);
+ }
}
}
}
diff --git a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
index 682f700..b29a9cd 100644
--- a/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
+++ b/src/com/android/contacts/socialwidget/SocialWidgetProvider.java
@@ -36,6 +36,7 @@
import android.net.Uri;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsContract.StreamItems;
+import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
@@ -204,7 +205,7 @@
} else {
// TODO: Rotate between all the stream items?
StreamItemEntry streamItem = streamItems.get(0);
- CharSequence status = streamItem.getText();
+ CharSequence status = Html.fromHtml(streamItem.getText());
if (status.length() <= SHORT_SNIPPET_LENGTH) {
sb.append("\n");
} else {