diff options
Diffstat (limited to 'java/com/android/dialer')
23 files changed, 521 insertions, 71 deletions
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java index d3fd36520..f5474eec6 100644 --- a/java/com/android/dialer/app/calllog/CallLogAdapter.java +++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java @@ -53,7 +53,6 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import com.android.contacts.common.ContactsUtils; -import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.app.R; import com.android.dialer.app.calllog.CallLogFragment.CallLogFragmentListener; import com.android.dialer.app.calllog.CallLogGroupBuilder.GroupCreator; @@ -73,6 +72,7 @@ import com.android.dialer.common.concurrent.AsyncTaskExecutor; import com.android.dialer.common.concurrent.AsyncTaskExecutors; import com.android.dialer.compat.android.provider.VoicemailCompat; import com.android.dialer.configprovider.ConfigProviderComponent; +import com.android.dialer.contacts.ContactsComponent; import com.android.dialer.duo.Duo; import com.android.dialer.duo.DuoComponent; import com.android.dialer.duo.DuoListener; @@ -506,7 +506,6 @@ public class CallLogAdapter extends GroupingListAdapter private final Map<Long, Integer> dayGroups = new ArrayMap<>(); private boolean loading = true; - private ContactsPreferences contactsPreferences; private boolean isSpamEnabled; @@ -551,8 +550,6 @@ public class CallLogAdapter extends GroupingListAdapter callLogGroupBuilder = new CallLogGroupBuilder(activity.getApplicationContext(), this); this.filteredNumberAsyncQueryHandler = Assert.isNotNull(filteredNumberAsyncQueryHandler); - contactsPreferences = new ContactsPreferences(this.activity); - blockReportSpamListener = new BlockReportSpamListener( this.activity, @@ -674,7 +671,6 @@ public class CallLogAdapter extends GroupingListAdapter if (PermissionsUtil.hasPermission(activity, android.Manifest.permission.READ_CONTACTS)) { contactInfoCache.start(); } - contactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); isSpamEnabled = SpamComponent.get(activity).spamSettings().isSpamEnabled(); getDuo().registerListener(this); notifyDataSetChanged(); @@ -1078,7 +1074,8 @@ public class CallLogAdapter extends GroupingListAdapter details.contactUri = info.lookupUri; details.namePrimary = info.name; details.nameAlternative = info.nameAlternative; - details.nameDisplayOrder = contactsPreferences.getDisplayOrder(); + details.nameDisplayOrder = + ContactsComponent.get(activity).contactDisplayPreferences().getDisplayOrder(); details.numberType = info.type; details.numberLabel = info.label; details.photoUri = info.photoUri; diff --git a/java/com/android/dialer/app/list/OldSpeedDialFragment.java b/java/com/android/dialer/app/list/OldSpeedDialFragment.java index 9b83d54ef..9922ee232 100644 --- a/java/com/android/dialer/app/list/OldSpeedDialFragment.java +++ b/java/com/android/dialer/app/list/OldSpeedDialFragment.java @@ -113,9 +113,6 @@ public class OldSpeedDialFragment extends Fragment public void onResume() { Trace.beginSection(TAG + " onResume"); super.onResume(); - if (contactTileAdapter != null) { - contactTileAdapter.refreshContactsPreferences(); - } if (PermissionsUtil.hasContactsReadPermissions(getContext())) { if (getLoaderManager().getLoader(LOADER_ID_CONTACT_TILE) == null) { getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, contactTileLoaderListener); diff --git a/java/com/android/dialer/app/list/PhoneFavoriteSquareTileView.java b/java/com/android/dialer/app/list/PhoneFavoriteSquareTileView.java index 6b41547c2..8fe67f4f0 100644 --- a/java/com/android/dialer/app/list/PhoneFavoriteSquareTileView.java +++ b/java/com/android/dialer/app/list/PhoneFavoriteSquareTileView.java @@ -104,7 +104,7 @@ public class PhoneFavoriteSquareTileView extends PhoneFavoriteTileView { @Override protected String getNameForView(ContactEntry contactEntry) { - return contactEntry.getPreferredDisplayName(); + return contactEntry.getPreferredDisplayName(getContext()); } public ContactEntry getContactEntry() { diff --git a/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java b/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java index a20185989..4cc48a6de 100644 --- a/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java +++ b/java/com/android/dialer/app/list/PhoneFavoritesTileAdapter.java @@ -37,10 +37,10 @@ import android.widget.BaseAdapter; import com.android.contacts.common.ContactTileLoaderFactory; import com.android.contacts.common.list.ContactEntry; import com.android.contacts.common.list.ContactTileView; -import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.app.R; import com.android.dialer.common.LogUtil; import com.android.dialer.contactphoto.ContactPhotoManager; +import com.android.dialer.contacts.ContactsComponent; import com.android.dialer.duo.Duo; import com.android.dialer.duo.DuoComponent; import com.android.dialer.logging.InteractionEvent; @@ -78,11 +78,11 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop private OnDataSetChangedForAnimationListener dataSetChangedListener; private Context context; private Resources resources; - private ContactsPreferences contactsPreferences; private final Comparator<ContactEntry> contactEntryComparator = new Comparator<ContactEntry>() { @Override public int compare(ContactEntry lhs, ContactEntry rhs) { + return ComparisonChain.start() .compare(lhs.pinned, rhs.pinned) .compare(getPreferredSortName(lhs), getPreferredSortName(rhs)) @@ -90,11 +90,9 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop } private String getPreferredSortName(ContactEntry contactEntry) { - if (contactsPreferences.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY - || TextUtils.isEmpty(contactEntry.nameAlternative)) { - return contactEntry.namePrimary; - } - return contactEntry.nameAlternative; + return ContactsComponent.get(context) + .contactDisplayPreferences() + .getSortName(contactEntry.namePrimary, contactEntry.nameAlternative); } }; /** Back up of the temporarily removed Contact during dragging. */ @@ -121,7 +119,6 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop this.listener = listener; this.context = context; resources = context.getResources(); - contactsPreferences = new ContactsPreferences(this.context); numFrequents = 0; contactEntries = new ArrayList<>(); } @@ -140,11 +137,6 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop this.inDragging = inDragging; } - void refreshContactsPreferences() { - contactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); - contactsPreferences.refreshValue(ContactsPreferences.SORT_ORDER_KEY); - } - /** * Gets the number of frequents from the passed in cursor. * @@ -256,7 +248,6 @@ public class PhoneFavoritesTileAdapter extends BaseAdapter implements OnDragDrop (!TextUtils.isEmpty(nameAlternative)) ? nameAlternative : resources.getString(R.string.missing_name); - contact.nameDisplayOrder = contactsPreferences.getDisplayOrder(); contact.photoUri = (photoUri != null ? Uri.parse(photoUri) : null); contact.lookupKey = lookupKey; contact.lookupUri = diff --git a/java/com/android/dialer/app/res/xml/display_options_settings.xml b/java/com/android/dialer/app/res/xml/display_options_settings.xml index 0b4e11d47..60301dbe8 100644 --- a/java/com/android/dialer/app/res/xml/display_options_settings.xml +++ b/java/com/android/dialer/app/res/xml/display_options_settings.xml @@ -18,14 +18,22 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> - <com.android.contacts.common.preference.SortOrderPreference - android:dialogTitle="@string/display_options_sort_list_by" - android:key="sortOrder" - android:title="@string/display_options_sort_list_by"/> + <ListPreference + android:dialogTitle="@string/display_options_sort_list_by" + android:key="@string/display_options_sort_list_by_key" + android:summary="%s" + android:entries="@array/contact_sort_order_entries" + android:entryValues="@array/contact_sort_order_values" + android:title="@string/display_options_sort_list_by" + android:defaultValue="1"/> - <com.android.contacts.common.preference.DisplayOrderPreference - android:dialogTitle="@string/display_options_view_names_as" - android:key="displayOrder" - android:title="@string/display_options_view_names_as"/> + <ListPreference + android:dialogTitle="@string/display_options_view_names_as" + android:key="@string/display_options_view_names_as_key" + android:summary="%s" + android:entries="@array/contact_display_order_entries" + android:entryValues="@array/contact_display_order_values" + android:title="@string/display_options_view_names_as" + android:defaultValue="1"/> </PreferenceScreen> diff --git a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java index ae068ac6b..8181e21bf 100644 --- a/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java +++ b/java/com/android/dialer/binary/aosp/AospDialerRootComponent.java @@ -24,6 +24,7 @@ import com.android.dialer.calllog.config.CallLogConfigModule; import com.android.dialer.commandline.CommandLineModule; import com.android.dialer.common.concurrent.DialerExecutorModule; import com.android.dialer.configprovider.SharedPrefConfigProviderModule; +import com.android.dialer.contacts.ContactsModule; import com.android.dialer.duo.stub.StubDuoModule; import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule; import com.android.dialer.feedback.stub.StubFeedbackModule; @@ -57,6 +58,7 @@ import javax.inject.Singleton; CallLogModule.class, CallLogConfigModule.class, CommandLineModule.class, + ContactsModule.class, ContextModule.class, DialerExecutorModule.class, GlidePhotoManagerModule.class, diff --git a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java index 666a0be50..acf14b1ea 100644 --- a/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java +++ b/java/com/android/dialer/binary/basecomponent/BaseDialerRootComponent.java @@ -25,6 +25,7 @@ import com.android.dialer.calllog.ui.CallLogUiComponent; import com.android.dialer.commandline.CommandLineComponent; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.configprovider.ConfigProviderComponent; +import com.android.dialer.contacts.ContactsComponent; import com.android.dialer.duo.DuoComponent; import com.android.dialer.enrichedcall.EnrichedCallComponent; import com.android.dialer.feedback.FeedbackComponent; @@ -62,6 +63,7 @@ public interface BaseDialerRootComponent CallLogUiComponent.HasComponent, ConfigProviderComponent.HasComponent, CommandLineComponent.HasComponent, + ContactsComponent.HasComponent, DialerExecutorComponent.HasComponent, DuoComponent.HasComponent, EnrichedCallComponent.HasComponent, diff --git a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java index 622bd5d4f..35e7809ac 100644 --- a/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java +++ b/java/com/android/dialer/binary/google/GoogleStubDialerRootComponent.java @@ -24,6 +24,7 @@ import com.android.dialer.calllog.config.CallLogConfigModule; import com.android.dialer.commandline.CommandLineModule; import com.android.dialer.common.concurrent.DialerExecutorModule; import com.android.dialer.configprovider.SharedPrefConfigProviderModule; +import com.android.dialer.contacts.ContactsModule; import com.android.dialer.duo.stub.StubDuoModule; import com.android.dialer.enrichedcall.stub.StubEnrichedCallModule; import com.android.dialer.feedback.stub.StubFeedbackModule; @@ -62,6 +63,7 @@ import javax.inject.Singleton; CallLogConfigModule.class, CommandLineModule.class, ContextModule.class, + ContactsModule.class, DialerExecutorModule.class, GlidePhotoManagerModule.class, MapsModule.class, diff --git a/java/com/android/dialer/calllogutils/PhoneCallDetails.java b/java/com/android/dialer/calllogutils/PhoneCallDetails.java index fe8bfde43..7212fa960 100644 --- a/java/com/android/dialer/calllogutils/PhoneCallDetails.java +++ b/java/com/android/dialer/calllogutils/PhoneCallDetails.java @@ -25,8 +25,8 @@ import android.support.annotation.Nullable; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; import com.android.contacts.common.ContactsUtils.UserType; -import com.android.contacts.common.preference.ContactsPreferences; import com.android.contacts.common.util.ContactDisplayUtils; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences.DisplayOrder; import com.android.dialer.logging.ContactSource; import com.android.dialer.phonenumbercache.ContactInfo; @@ -65,7 +65,7 @@ public class PhoneCallDetails { * The user's preference on name display order, last name first or first time first. {@see * ContactsPreferences} */ - public int nameDisplayOrder; + public DisplayOrder nameDisplayOrder; // The type of phone, e.g., {@link Phone#TYPE_HOME}, 0 if not available. public int numberType; // The custom label associated with the phone number in the contact, or the empty string. @@ -183,8 +183,7 @@ public class PhoneCallDetails { * @return the preferred name */ public CharSequence getPreferredName() { - if (nameDisplayOrder == ContactsPreferences.DISPLAY_ORDER_PRIMARY - || TextUtils.isEmpty(nameAlternative)) { + if (nameDisplayOrder == DisplayOrder.PRIMARY || TextUtils.isEmpty(nameAlternative)) { return namePrimary; } return nameAlternative; diff --git a/java/com/android/dialer/contacts/ContactsComponent.java b/java/com/android/dialer/contacts/ContactsComponent.java new file mode 100644 index 000000000..5c4097ace --- /dev/null +++ b/java/com/android/dialer/contacts/ContactsComponent.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 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.dialer.contacts; + +import android.content.Context; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; +import com.android.dialer.inject.HasRootComponent; +import dagger.Subcomponent; + +/** Component for contacts related utilities */ +@Subcomponent +public abstract class ContactsComponent { + + public abstract ContactDisplayPreferences contactDisplayPreferences(); + + public static ContactsComponent get(Context context) { + return ((HasComponent) ((HasRootComponent) context.getApplicationContext()).component()) + .contactsComponent(); + } + + /** Used to refer to the root application component. */ + public interface HasComponent { + ContactsComponent contactsComponent(); + } +} diff --git a/java/com/android/dialer/contacts/ContactsModule.java b/java/com/android/dialer/contacts/ContactsModule.java new file mode 100644 index 000000000..979c525eb --- /dev/null +++ b/java/com/android/dialer/contacts/ContactsModule.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 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.dialer.contacts; + +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferencesImpl; +import com.android.dialer.inject.DialerVariant; +import com.android.dialer.inject.InstallIn; +import dagger.Binds; +import dagger.Module; + +/** Module for standard {@link ContactsComponent} */ +@InstallIn(variants = {DialerVariant.DIALER_TEST}) +@Module +public abstract class ContactsModule { + @Binds + public abstract ContactDisplayPreferences to(ContactDisplayPreferencesImpl impl); +} diff --git a/java/com/android/dialer/contacts/displaypreference/AndroidManifest.xml b/java/com/android/dialer/contacts/displaypreference/AndroidManifest.xml new file mode 100644 index 000000000..27514615e --- /dev/null +++ b/java/com/android/dialer/contacts/displaypreference/AndroidManifest.xml @@ -0,0 +1,18 @@ +<!-- + ~ Copyright (C) 2018 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 + --> +<manifest + package="com.android.dialer.contacts.displaypreference"> +</manifest>
\ No newline at end of file diff --git a/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferences.java b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferences.java new file mode 100644 index 000000000..dca466ebf --- /dev/null +++ b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferences.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2018 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.dialer.contacts.displaypreference; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.annotation.StringRes; +import android.text.TextUtils; +import java.util.Arrays; + +/** Handles name ordering of a contact (Given name first or family name first.) */ +public interface ContactDisplayPreferences { + + /** + * A enum whose value is a String from a Android string resource which can only be resolved at run + * time. + */ + interface StringResEnum { + + @StringRes + int getStringRes(); + + default String getValue(Context context) { + return context.getString(getStringRes()); + } + + static <T extends Enum<T> & StringResEnum> T fromValue( + Context context, T[] values, String value) { + return Arrays.stream(values) + .filter(enumValue -> TextUtils.equals(enumValue.getValue(context), value)) + // MoreCollectors.onlyElement() is not available to android guava. + .reduce( + (a, b) -> { + throw new AssertionError("multiple result"); + }) + .get(); + } + } + + /** Order when displaying the name; */ + enum DisplayOrder implements StringResEnum { + + /** + * The default display order of a name. For western names it will be "Given Family". For + * unstructured names like east asian this will be the only order. + * + * @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_PRIMARY + */ + PRIMARY(R.string.display_options_view_given_name_first_value), + /** + * The alternative display order of a name. For western names it will be "Family, Given". For + * unstructured names like east asian this order will be ignored and treated as primary. + * + * @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_ALTERNATIVE + */ + ALTERNATIVE(R.string.display_options_view_family_name_first_value); + + @StringRes private final int value; + + DisplayOrder(@StringRes int value) { + this.value = value; + } + + @Override + @StringRes + public int getStringRes() { + return value; + } + + static DisplayOrder fromValue(Context context, String value) { + return StringResEnum.fromValue(context, DisplayOrder.values(), value); + } + } + + /** + * Order when sorting the name. In some conventions, names are displayed as given name first, but + * sorted by family name. + */ + enum SortOrder implements StringResEnum { + /** + * Sort by the default display order of a name. For western names it will be "Given Family". For + * unstructured names like east asian this will be the only order. + * + * @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_PRIMARY + */ + BY_PRIMARY(R.string.display_options_sort_by_given_name_value), + /** + * Sort by the alternative display order of a name. For western names it will be "Family, + * Given". For unstructured names like east asian this order will be ignored and treated as + * primary. + * + * @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_ALTERNATIVE + */ + BY_ALTERNATIVE(R.string.display_options_sort_by_family_name_value); + + @StringRes private final int value; + + SortOrder(@StringRes int value) { + this.value = value; + } + + @Override + @StringRes + public int getStringRes() { + return value; + } + + static SortOrder fromValue(Context context, String value) { + return StringResEnum.fromValue(context, SortOrder.values(), value); + } + } + + DisplayOrder getDisplayOrder(); + + void setDisplayOrder(DisplayOrder displayOrder); + + SortOrder getSortOrder(); + + void setSortOrder(SortOrder sortOrder); + + /** Selects display name based on {@link DisplayOrder} */ + default String getDisplayName(@Nullable String primaryName, @Nullable String alternativeName) { + if (TextUtils.isEmpty(alternativeName)) { + return primaryName; + } + switch (getDisplayOrder()) { + case PRIMARY: + return primaryName; + case ALTERNATIVE: + return alternativeName; + } + throw new AssertionError("exhaustive switch"); + } + + /** Selects sort name based on {@link SortOrder} */ + default String getSortName(@Nullable String primaryName, @Nullable String alternativeName) { + if (TextUtils.isEmpty(alternativeName)) { + return primaryName; + } + switch (getSortOrder()) { + case BY_PRIMARY: + return primaryName; + case BY_ALTERNATIVE: + return alternativeName; + } + throw new AssertionError("exhaustive switch"); + } +} diff --git a/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java new file mode 100644 index 000000000..6072cc12c --- /dev/null +++ b/java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2018 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.dialer.contacts.displaypreference; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.UserManager; +import android.preference.PreferenceManager; +import com.android.dialer.inject.ApplicationContext; +import javax.inject.Inject; + +/** Implementation of {@link ContactDisplayPreferences} backed by a {@link SharedPreferences} */ +public final class ContactDisplayPreferencesImpl implements ContactDisplayPreferences { + + private final Context appContext; + private final SharedPreferences sharedPreferences; + private final String displayOrderKey; + private final String sortOrderKey; + + @Inject + ContactDisplayPreferencesImpl(@ApplicationContext Context appContext) { + this.appContext = appContext; + // @Unencrypted preference would be a better choice, but Android Preference only supports the + // default file. Names cannot be shown on @Unencrypted anyway. + this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext); + displayOrderKey = appContext.getString(R.string.display_options_view_names_as_key); + sortOrderKey = appContext.getString(R.string.display_options_sort_list_by_key); + } + + @Override + public DisplayOrder getDisplayOrder() { + migrate(); + if (!sharedPreferences.contains(displayOrderKey)) { + return DisplayOrder.PRIMARY; + } + return DisplayOrder.fromValue(appContext, sharedPreferences.getString(displayOrderKey, null)); + } + + @Override + public void setDisplayOrder(DisplayOrder displayOrder) { + sharedPreferences.edit().putString(displayOrderKey, displayOrder.getValue(appContext)).apply(); + } + + @Override + public SortOrder getSortOrder() { + migrate(); + if (!sharedPreferences.contains(sortOrderKey)) { + return SortOrder.BY_PRIMARY; + } + return SortOrder.fromValue(appContext, sharedPreferences.getString(sortOrderKey, null)); + } + + @Override + public void setSortOrder(SortOrder sortOrder) { + sharedPreferences.edit().putString(sortOrderKey, sortOrder.getValue(appContext)).apply(); + } + + /** + * Moves the stored values to the standard location. + * + * <p>Usually preferences are stored in {@code package.name_preferences.xml}. However the old + * com.android.contacts.common.preference.ContactsPreferences stored it in {@code + * package.name.xml} which is incompatible with the regular {@link android.preference.Preference} + * widgets. + */ + private void migrate() { + if (!appContext.getSystemService(UserManager.class).isUserUnlocked()) { + return; + } + SharedPreferences oldPreference = + appContext.getSharedPreferences(appContext.getPackageName(), Context.MODE_PRIVATE); + if (oldPreference.contains(displayOrderKey) || oldPreference.contains(sortOrderKey)) { + sharedPreferences + .edit() + .putString( + displayOrderKey, + translateLegacyDisplayOrder(oldPreference.getInt(displayOrderKey, 1))) + .putString(sortOrderKey, translateLegacySortOrder(oldPreference.getInt(sortOrderKey, 1))) + .apply(); + oldPreference.edit().remove(displayOrderKey).remove(sortOrderKey).apply(); + } + } + + private String translateLegacyDisplayOrder(int legacyValue) { + switch (legacyValue) { + case 2: + return DisplayOrder.ALTERNATIVE.getValue(appContext); + default: + return DisplayOrder.PRIMARY.getValue(appContext); + } + } + + private String translateLegacySortOrder(int legacyValue) { + switch (legacyValue) { + case 2: + return SortOrder.BY_ALTERNATIVE.getValue(appContext); + default: + return SortOrder.BY_PRIMARY.getValue(appContext); + } + } +} diff --git a/java/com/android/dialer/contacts/displaypreference/res/values/display_preference.xml b/java/com/android/dialer/contacts/displaypreference/res/values/display_preference.xml new file mode 100644 index 000000000..b74b8b999 --- /dev/null +++ b/java/com/android/dialer/contacts/displaypreference/res/values/display_preference.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 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> + <string-array name="contact_display_order_entries"> + <item>@string/display_options_view_given_name_first</item> + <item>@string/display_options_view_family_name_first</item> + </string-array> + + <string-array name="contact_display_order_values"> + <item>@string/display_options_view_given_name_first_value</item> + <item>@string/display_options_view_family_name_first_value</item> + </string-array> + + <string-array name="contact_sort_order_entries"> + <item>@string/display_options_sort_by_given_name</item> + <item>@string/display_options_sort_by_family_name</item> + </string-array> + + <string-array name="contact_sort_order_values"> + <item>@string/display_options_sort_by_given_name_value</item> + <item>@string/display_options_sort_by_family_name_value</item> + </string-array> +</resources>
\ No newline at end of file diff --git a/java/com/android/dialer/contacts/displaypreference/res/values/strings.xml b/java/com/android/dialer/contacts/displaypreference/res/values/strings.xml new file mode 100644 index 000000000..8914ddfa4 --- /dev/null +++ b/java/com/android/dialer/contacts/displaypreference/res/values/strings.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 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:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- Contact preferences related strings --> + + <!-- Label of the "sort by" display option --> + <string name="display_options_sort_list_by">Sort by</string> + + <string translatable="false" name="display_options_sort_list_by_key">android.contacts.SORT_ORDER</string> + + <!-- An allowable value for the "sort list by" contact display option --> + <string name="display_options_sort_by_given_name">First name</string> + + <string translatable="false" name="display_options_sort_by_given_name_value">sort_by_given_name</string> + + <!-- An allowable value for the "sort list by" contact display option --> + <string name="display_options_sort_by_family_name">Last name</string> + + <string translatable="false" name="display_options_sort_by_family_name_value">sort_by_family_name</string> + + <!-- Label of the "name format" display option [CHAR LIMIT=64]--> + <string name="display_options_view_names_as">Name format</string> + <string translatable="false" name="display_options_view_names_as_key">android.contacts.DISPLAY_ORDER</string> + + <!-- An allowable value for the "view names as" contact display option --> + <string name="display_options_view_given_name_first">First name first</string> + + <string translatable="false" name="display_options_view_given_name_first_value">view_given_name_first</string> + + <!-- An allowable value for the "view names as" contact display option --> + <string name="display_options_view_family_name_first">Last name first</string> + + <string translatable="false" name="display_options_view_family_name_first_value">view_family_name_first</string> +</resources> diff --git a/java/com/android/dialer/contactsfragment/ContactsCursorLoader.java b/java/com/android/dialer/contactsfragment/ContactsCursorLoader.java index e55f95149..d74afe538 100644 --- a/java/com/android/dialer/contactsfragment/ContactsCursorLoader.java +++ b/java/com/android/dialer/contactsfragment/ContactsCursorLoader.java @@ -21,7 +21,7 @@ import android.content.CursorLoader; import android.net.Uri; import android.provider.ContactsContract.Contacts; import android.text.TextUtils; -import com.android.contacts.common.preference.ContactsPreferences; +import com.android.dialer.contacts.ContactsComponent; /** Cursor Loader for {@link ContactsFragment}. */ final class ContactsCursorLoader extends CursorLoader { @@ -61,12 +61,13 @@ final class ContactsCursorLoader extends CursorLoader { } private static String[] getProjection(Context context) { - ContactsPreferences contactsPrefs = new ContactsPreferences(context); - boolean displayOrderPrimary = - (contactsPrefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY); - return displayOrderPrimary - ? CONTACTS_PROJECTION_DISPLAY_NAME_PRIMARY - : CONTACTS_PROJECTION_DISPLAY_NAME_ALTERNATIVE; + switch (ContactsComponent.get(context).contactDisplayPreferences().getDisplayOrder()) { + case PRIMARY: + return CONTACTS_PROJECTION_DISPLAY_NAME_PRIMARY; + case ALTERNATIVE: + return CONTACTS_PROJECTION_DISPLAY_NAME_ALTERNATIVE; + } + throw new AssertionError("exhaustive switch"); } private static String getWhere(Context context, boolean hasPhoneNumbers) { @@ -78,10 +79,14 @@ final class ContactsCursorLoader extends CursorLoader { } private static String getSortKey(Context context) { - ContactsPreferences contactsPrefs = new ContactsPreferences(context); - boolean sortOrderPrimary = - (contactsPrefs.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY); - return sortOrderPrimary ? Contacts.SORT_KEY_PRIMARY : Contacts.SORT_KEY_ALTERNATIVE; + + switch (ContactsComponent.get(context).contactDisplayPreferences().getSortOrder()) { + case BY_PRIMARY: + return Contacts.SORT_KEY_PRIMARY; + case BY_ALTERNATIVE: + return Contacts.SORT_KEY_ALTERNATIVE; + } + throw new AssertionError("exhaustive switch"); } /** Update cursor loader to filter contacts based on the provided query. */ diff --git a/java/com/android/dialer/contactsfragment/ContactsFragment.java b/java/com/android/dialer/contactsfragment/ContactsFragment.java index 794a5b91c..f40abec0d 100644 --- a/java/com/android/dialer/contactsfragment/ContactsFragment.java +++ b/java/com/android/dialer/contactsfragment/ContactsFragment.java @@ -41,8 +41,6 @@ import android.view.View.OnScrollChangeListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import com.android.contacts.common.preference.ContactsPreferences; -import com.android.contacts.common.preference.ContactsPreferences.ChangeListener; import com.android.dialer.common.Assert; import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; @@ -60,8 +58,7 @@ import java.util.Arrays; public class ContactsFragment extends Fragment implements LoaderCallbacks<Cursor>, OnScrollChangeListener, - OnEmptyViewActionButtonClickedListener, - ChangeListener { + OnEmptyViewActionButtonClickedListener { /** An enum for the different types of headers that be inserted at position 0 in the list. */ @Retention(RetentionPolicy.SOURCE) @@ -98,7 +95,6 @@ public class ContactsFragment extends Fragment private @Header int header; - private ContactsPreferences contactsPrefs; private boolean hasPhoneNumbers; private String query; @@ -154,8 +150,6 @@ public class ContactsFragment extends Fragment @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - contactsPrefs = new ContactsPreferences(getContext()); - contactsPrefs.registerChangeListener(this); header = getArguments().getInt(EXTRA_HEADER); hasPhoneNumbers = getArguments().getBoolean(EXTRA_HAS_PHONE_NUMBERS); if (savedInstanceState == null) { @@ -224,7 +218,8 @@ public class ContactsFragment extends Fragment } @Override - public void onChange() { + public void onResume() { + super.onResume(); if (getActivity() != null && isAdded() && PermissionsUtil.hasContactsReadPermissions(getContext())) { @@ -268,7 +263,6 @@ public class ContactsFragment extends Fragment recyclerView.setAdapter(null); recyclerView.setOnScrollChangeListener(null); adapter = null; - contactsPrefs.unregisterChangeListener(); } /* diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java index 7caa314f3..f4ed21ee4 100644 --- a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java +++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java @@ -27,8 +27,10 @@ import android.provider.ContactsContract.Directory; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.text.TextUtils; -import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.common.LogUtil; +import com.android.dialer.contacts.ContactsComponent; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences.DisplayOrder; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences.SortOrder; import com.android.dialer.searchfragment.common.Projections; import com.android.dialer.searchfragment.common.SearchCursor; import com.android.dialer.smartdial.SmartDialCursorLoader; @@ -55,9 +57,9 @@ public final class SearchContactsCursorLoader extends CursorLoader { } private static String[] getProjection(Context context) { - ContactsPreferences contactsPrefs = new ContactsPreferences(context); boolean displayOrderPrimary = - (contactsPrefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY); + (ContactsComponent.get(context).contactDisplayPreferences().getDisplayOrder() + == DisplayOrder.PRIMARY); return displayOrderPrimary ? Projections.CP2_PROJECTION : Projections.CP2_PROJECTION_ALTERNATIVE; @@ -70,9 +72,9 @@ public final class SearchContactsCursorLoader extends CursorLoader { } private static String getSortKey(Context context) { - ContactsPreferences contactsPrefs = new ContactsPreferences(context); boolean sortOrderPrimary = - (contactsPrefs.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY); + (ContactsComponent.get(context).contactDisplayPreferences().getSortOrder() + == SortOrder.BY_PRIMARY); return sortOrderPrimary ? Phone.SORT_KEY_PRIMARY : Phone.SORT_KEY_ALTERNATIVE; } diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index fd6db75e9..65ce87340 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -404,7 +404,7 @@ public final class NewSearchFragment extends Fragment } // If the user dismissed the prompt without granting us the permission, don't load the cursor. - if (!PermissionsUtil.hasLocationPermissions(getContext())) { + if (getContext() == null || !PermissionsUtil.hasLocationPermissions(getContext())) { return; } diff --git a/java/com/android/dialer/shortcuts/DynamicShortcuts.java b/java/com/android/dialer/shortcuts/DynamicShortcuts.java index be9e088e1..e39dc27a9 100644 --- a/java/com/android/dialer/shortcuts/DynamicShortcuts.java +++ b/java/com/android/dialer/shortcuts/DynamicShortcuts.java @@ -124,7 +124,7 @@ final class DynamicShortcuts { DialerShortcut.builder() .setContactId(entry.id) .setLookupKey(entry.lookupKey) - .setDisplayName(entry.getPreferredDisplayName()) + .setDisplayName(entry.getPreferredDisplayName(context)) .setRank(rank++) .build(); newDynamicShortcutsById.put(shortcut.getShortcutId(), shortcut); diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java index 72f0a68c6..b0b83ac32 100644 --- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java +++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemMutator.java @@ -31,13 +31,14 @@ import android.support.annotation.MainThread; import android.support.annotation.WorkerThread; import android.util.ArrayMap; import android.util.ArraySet; -import com.android.contacts.common.preference.ContactsPreferences; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.Annotations.BackgroundExecutor; import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener; import com.android.dialer.common.concurrent.DialerFutureSerializer; import com.android.dialer.common.database.Selection; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences; +import com.android.dialer.contacts.displaypreference.ContactDisplayPreferences.DisplayOrder; import com.android.dialer.duo.DuoComponent; import com.android.dialer.inject.ApplicationContext; import com.android.dialer.speeddial.database.SpeedDialEntry; @@ -84,15 +85,16 @@ public final class SpeedDialUiItemMutator { private final ListeningExecutorService backgroundExecutor; // Used to ensure that only one refresh flow runs at a time. private final DialerFutureSerializer dialerFutureSerializer = new DialerFutureSerializer(); - private final ContactsPreferences contactsPreferences; + private final ContactDisplayPreferences contactDisplayPreferences; @Inject public SpeedDialUiItemMutator( @ApplicationContext Context appContext, - @BackgroundExecutor ListeningExecutorService backgroundExecutor) { + @BackgroundExecutor ListeningExecutorService backgroundExecutor, + ContactDisplayPreferences contactDisplayPreferences) { this.appContext = appContext; this.backgroundExecutor = backgroundExecutor; - this.contactsPreferences = new ContactsPreferences(appContext); + this.contactDisplayPreferences = contactDisplayPreferences; } /** @@ -183,7 +185,6 @@ public final class SpeedDialUiItemMutator { @WorkerThread private ImmutableList<SpeedDialUiItem> insertNewContactEntry(Uri contactUri) { Assert.isWorkerThread(); - contactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); try (Cursor cursor = appContext .getContentResolver() @@ -225,7 +226,6 @@ public final class SpeedDialUiItemMutator { private ImmutableList<SpeedDialUiItem> loadSpeedDialUiItemsInternal() { Trace.beginSection("loadSpeedDialUiItemsInternal"); Assert.isWorkerThread(); - contactsPreferences.refreshValue(ContactsPreferences.DISPLAY_ORDER_KEY); Trace.beginSection("getAllEntries"); SpeedDialEntryDao db = getSpeedDialEntryDao(); Trace.endSection(); // getAllEntries @@ -663,6 +663,6 @@ public final class SpeedDialUiItemMutator { } private boolean isPrimaryDisplayNameOrder() { - return contactsPreferences.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY; + return contactDisplayPreferences.getDisplayOrder() == DisplayOrder.PRIMARY; } } diff --git a/java/com/android/dialer/theme/common/res/values/text_styles.xml b/java/com/android/dialer/theme/common/res/values/text_styles.xml index def5862d4..0d1fd850e 100644 --- a/java/com/android/dialer/theme/common/res/values/text_styles.xml +++ b/java/com/android/dialer/theme/common/res/values/text_styles.xml @@ -33,7 +33,7 @@ <style name="Dialer.TextAppearance.SubHeader" parent="TextAppearance.AppCompat"> <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:textSize">16sp</item> + <item name="android:textSize">14sp</item> <item name="android:fontFamily">sans-serif-medium</item> </style> |