summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/contacts
diff options
context:
space:
mode:
authortwyen <twyen@google.com>2018-06-25 12:36:26 -0700
committerCopybara-Service <copybara-piper@google.com>2018-06-26 13:42:08 -0700
commit5578d928bf777f721ec0ec04c84ddb7d3ea56edb (patch)
tree150f643cf67aee21a2ac730d3f7b1f6cada7db47 /java/com/android/dialer/contacts
parent03bacec1394032712c534605476fb634b85eee28 (diff)
Refactor ContactPreference
Moving it outside contacts.commons reduces dependency to legacy code. Also removed redundant implementations such as caching SharedPreferences (it is already cached), custom ListPreferences (standard ListPreferences already have what we want), and corrected preference storage location (allow standard ListPreferences to work) TEST=TAP Test: TAP PiperOrigin-RevId: 202000393 Change-Id: I45374e610b3510784b5a4da92e5d8462cbfc92bb
Diffstat (limited to 'java/com/android/dialer/contacts')
-rw-r--r--java/com/android/dialer/contacts/ContactsComponent.java39
-rw-r--r--java/com/android/dialer/contacts/ContactsModule.java32
-rw-r--r--java/com/android/dialer/contacts/displaypreference/AndroidManifest.xml18
-rw-r--r--java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferences.java162
-rw-r--r--java/com/android/dialer/contacts/displaypreference/ContactDisplayPreferencesImpl.java115
-rw-r--r--java/com/android/dialer/contacts/displaypreference/res/values/display_preference.xml37
-rw-r--r--java/com/android/dialer/contacts/displaypreference/res/values/strings.xml48
7 files changed, 451 insertions, 0 deletions
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>