blob: d6dd8c6da990573bba8f6c7e381e15d8d813637e [file] [log] [blame]
/*
* 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.car.dialer.ui.contact;
import android.app.Application;
import android.content.Context;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MediatorLiveData;
import com.android.car.dialer.R;
import com.android.car.dialer.livedata.SharedPreferencesLiveData;
import com.android.car.dialer.widget.WorkerExecutor;
import com.android.car.telephony.common.Contact;
import com.android.car.telephony.common.InMemoryPhoneBook;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Future;
/**
* View model for {@link ContactListFragment}.
*/
public class ContactListViewModel extends AndroidViewModel {
public static final int SORT_BY_FIRST_NAME = 1;
public static final int SORT_BY_LAST_NAME = 2;
private final Context mContext;
private final LiveData<Pair<Integer, List<Contact>>> mSortedContactListLiveData;
public ContactListViewModel(@NonNull Application application) {
super(application);
mContext = application.getApplicationContext();
SharedPreferencesLiveData preferencesLiveData =
new SharedPreferencesLiveData(mContext, R.string.sort_order_key);
LiveData<List<Contact>> contactListLiveData = InMemoryPhoneBook.get().getContactsLiveData();
mSortedContactListLiveData = new SortedContactListLiveData(
mContext, contactListLiveData, preferencesLiveData);
}
/**
* Returns a live data which represents a list of all contacts.
*/
public LiveData<Pair<Integer, List<Contact>>> getAllContacts() {
return mSortedContactListLiveData;
}
private static class SortedContactListLiveData
extends MediatorLiveData<Pair<Integer, List<Contact>>> {
private final LiveData<List<Contact>> mContactListLiveData;
private final SharedPreferencesLiveData mPreferencesLiveData;
private final Context mContext;
private Future<?> mRunnableFuture;
/**
* 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.
* Phone Dialer uses the same method for sorting given names.
*
* @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_PRIMARY
*/
private final Comparator<Contact> mFirstNameComparator =
(o1, o2) -> o1.compareByDisplayName(o2);
/**
* 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.
* Phone Dialer uses the same method for sorting family names.
*
* @see android.provider.ContactsContract.Contacts#DISPLAY_NAME_ALTERNATIVE
*/
private final Comparator<Contact> mLastNameComparator =
(o1, o2) -> o1.compareByAltDisplayName(o2);
private SortedContactListLiveData(Context context,
@NonNull LiveData<List<Contact>> contactListLiveData,
@NonNull SharedPreferencesLiveData sharedPreferencesLiveData) {
mContext = context;
mContactListLiveData = contactListLiveData;
mPreferencesLiveData = sharedPreferencesLiveData;
addSource(mPreferencesLiveData, (trigger) -> updateSortedContactList());
addSource(mContactListLiveData, (trigger) -> updateSortedContactList());
}
private void updateSortedContactList() {
if (mContactListLiveData.getValue() == null) {
setValue(null);
return;
}
String key = mPreferencesLiveData.getKey();
String firstNameSort = mContext.getResources().getString(
R.string.give_name_first_title);
List<Contact> contactList = mContactListLiveData.getValue();
Comparator<Contact> comparator;
Integer sortMethod;
if (mPreferencesLiveData.getValue() == null
|| firstNameSort.equals(
mPreferencesLiveData.getValue().getString(key, firstNameSort))) {
comparator = mFirstNameComparator;
sortMethod = SORT_BY_FIRST_NAME;
} else {
comparator = mLastNameComparator;
sortMethod = SORT_BY_LAST_NAME;
}
// SingleThreadPoolExecutor is used here to avoid multiple threads sorting the list
// at the same time.
if (mRunnableFuture != null) {
mRunnableFuture.cancel(true);
}
Runnable runnable = () -> {
Collections.sort(contactList, comparator);
postValue(new Pair<>(sortMethod, contactList));
};
mRunnableFuture = WorkerExecutor.getInstance().getSingleThreadExecutor().submit(
runnable);
}
@Override
protected void onInactive() {
super.onInactive();
if (mRunnableFuture != null) {
mRunnableFuture.cancel(true);
}
}
}
}