Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2cad223 authored by Walter Jang's avatar Walter Jang
Browse files

Restore the "Contacts to display" custom filter (2/3)

* Revert "Remove AccountFilterActivity and its usage (ContactsCommon)"
  This reverts commit cc8f7406b3c34587941dac11ad24966ab3f8e417.
* ContactListFilterView and CustomContatListFilterActivity are
  unchanged from their state before when they were removed.
* AccountFilterActitivy has been altered to only show
  FILTER_TYPE_ALL_ACCOUNTS and FILTER_TYPE_CUSTOM filter types
  (instead of using AccountFilterUtil.FilterLoader) and to
  set which one is checked based on the persisted state and not
  the extra passed to the Activity.  So the KEY_EXTRA_CURRENT_FILTER
  has been removed.
* AccountFitlerUtil#updateAccountFilterTitleForPeople
  and #updateAccountFitlerTitleForPhone methods were not restored
  since the list header titles are now set elsewhere.
* Finally, we added a new "Contacts to display" item to Settings
  after "Name format" and make a call to
  AccountFilterUtil.handleAccountFilterResult when the
  AccountFilterActivity returns to persist either the
  FILTER_TYPE_ALL_ACCOUNTS or FILTER_TYPE_CUSTOM filter type.

Bug 29185471

Change-Id: I5f199f47f9d0098065790d4d8483d786ad9fcb5b
parent 3bae6dba
Loading
Loading
Loading
Loading
+198 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.contacts.common.list;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;

import com.android.contacts.common.R;
import com.android.contacts.common.model.AccountTypeManager;

import java.util.ArrayList;
import java.util.List;

/**
 * Shows a list of all available accounts, letting the user select under which account to view
 * contacts.
 */
public class AccountFilterActivity extends Activity implements AdapterView.OnItemClickListener {

    private static final int SUBACTIVITY_CUSTOMIZE_FILTER = 0;

    public static final String EXTRA_CONTACT_LIST_FILTER = "contactListFilter";

    private ListView mListView;

    // The default contact list type, it should be either FILTER_TYPE_ALL_ACCOUNTS or
    // FILTER_TYPE_CUSTOM, since those are the only two options we give the user.
    private int mCurrentFilterType;

    private ContactListFilterView mCustomFilterView; // the "Customize" filter

    private boolean mIsCustomFilterViewSelected;

    @Override
    protected void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.contact_list_filter);

        mListView = (ListView) findViewById(android.R.id.list);
        mListView.setOnItemClickListener(this);

        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        mCurrentFilterType = ContactListFilterController.getInstance(this).isCustomFilterPersisted()
                ? ContactListFilter.FILTER_TYPE_CUSTOM
                : ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS;

        // We don't need to use AccountFilterUtil.FilterLoader since we only want to show
        // the "All contacts" and "Customize" options.
        final List<ContactListFilter> filters = new ArrayList<>();
        filters.add(ContactListFilter.createFilterWithType(
                ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));
        filters.add(ContactListFilter.createFilterWithType(
                ContactListFilter.FILTER_TYPE_CUSTOM));
        mListView.setAdapter(new FilterListAdapter(this, filters, mCurrentFilterType));
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        final ContactListFilterView listFilterView = (ContactListFilterView) view;
        final ContactListFilter filter = (ContactListFilter) view.getTag();
        if (filter == null) return; // Just in case
        if (filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM) {
            mCustomFilterView = listFilterView;
            mIsCustomFilterViewSelected = listFilterView.isChecked();
            final Intent intent = new Intent(this,
                    CustomContactListFilterActivity.class);
            listFilterView.setActivated(true);
            // Switching activity has the highest priority. So when we open another activity, the
            // announcement that indicates an account is checked will be interrupted. This is the
            // way to overcome -- View.announceForAccessibility(CharSequence text);
            listFilterView.announceForAccessibility(listFilterView.generateContentDescription());
            startActivityForResult(intent, SUBACTIVITY_CUSTOMIZE_FILTER);
        } else {
            listFilterView.setActivated(true);
            listFilterView.announceForAccessibility(listFilterView.generateContentDescription());
            final Intent intent = new Intent();
            intent.putExtra(EXTRA_CONTACT_LIST_FILTER, filter);
            setResult(Activity.RESULT_OK, intent);
            finish();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_CANCELED && mCustomFilterView != null &&
                !mIsCustomFilterViewSelected) {
            mCustomFilterView.setActivated(false);
            return;
        }

        if (resultCode != Activity.RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case SUBACTIVITY_CUSTOMIZE_FILTER: {
                final Intent intent = new Intent();
                ContactListFilter filter = ContactListFilter.createFilterWithType(
                        ContactListFilter.FILTER_TYPE_CUSTOM);
                intent.putExtra(EXTRA_CONTACT_LIST_FILTER, filter);
                setResult(Activity.RESULT_OK, intent);
                finish();
                break;
            }
        }
    }

    private static class FilterListAdapter extends BaseAdapter {
        private final List<ContactListFilter> mFilters;
        private final LayoutInflater mLayoutInflater;
        private final AccountTypeManager mAccountTypes;
        private final int mCurrentFilter;

        public FilterListAdapter(
                Context context, List<ContactListFilter> filters, int current) {
            mLayoutInflater = (LayoutInflater) context.getSystemService
                    (Context.LAYOUT_INFLATER_SERVICE);
            mFilters = filters;
            mCurrentFilter = current;
            mAccountTypes = AccountTypeManager.getInstance(context);
        }

        @Override
        public int getCount() {
            return mFilters.size();
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public ContactListFilter getItem(int position) {
            return mFilters.get(position);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            final ContactListFilterView view;
            if (convertView != null) {
                view = (ContactListFilterView) convertView;
            } else {
                view = (ContactListFilterView) mLayoutInflater.inflate(
                        R.layout.contact_list_filter_item, parent, false);
            }
            view.setSingleAccount(mFilters.size() == 1);
            final ContactListFilter filter = mFilters.get(position);
            view.setContactListFilter(filter);
            view.bindView(mAccountTypes);
            view.setTag(filter);
            view.setActivated(filter.filterType == mCurrentFilter);
            return view;
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // We have two logical "up" Activities: People and Phone.
                // Instead of having one static "up" direction, behave like back as an
                // exceptional case.
                onBackPressed();
                return true;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -90,6 +90,16 @@ public final class ContactListFilter implements Comparable<ContactListFilter>, P
                /* accountType= */ null, /* accountName= */ null, /* dataSet= */ null, icon);
    }

    /**
     * Whether the given {@link ContactListFilter} has a filter type that should be displayed as
     * the default contacts list view.
     */
    public static boolean isContactsFilterType(ContactListFilter filter) {
        if (filter == null) return false;
        return filter.filterType == ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS
                || filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM;
    }

    /**
     * Returns true if this filter is based on data and may become invalid over time.
     */
+12 −2
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@ public abstract class ContactListFilterController {
     */
    public abstract ContactListFilter getFilter();

    /**  Whether the persisted filter is a custom filter. */
    public abstract boolean isCustomFilterPersisted();

    /**
     * @param filter the filter
     * @param persistent True when the given filter should be saved soon. False when the filter
@@ -105,13 +108,20 @@ class ContactListFilterControllerImpl extends ContactListFilterController {
        return mFilter;
    }

    @Override
    public boolean isCustomFilterPersisted() {
        final ContactListFilter filter =
                ContactListFilter.restoreDefaultPreferences(getSharedPreferences());
        return filter != null && filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM;
    }

    private SharedPreferences getSharedPreferences() {
        return PreferenceManager.getDefaultSharedPreferences(mContext);
    }

    @Override
    public void setContactListFilter(ContactListFilter filter, boolean persistent) {
        setContactListFilter(filter, persistent, true);
        setContactListFilter(filter, persistent, /* notifyListeners */ true);
    }

    private void setContactListFilter(ContactListFilter filter, boolean persistent,
@@ -130,7 +140,7 @@ class ContactListFilterControllerImpl extends ContactListFilterController {
    @Override
    public void selectCustomFilter() {
        setContactListFilter(ContactListFilter.createFilterWithType(
                ContactListFilter.FILTER_TYPE_CUSTOM), true);
                ContactListFilter.FILTER_TYPE_CUSTOM), /* persistent */ true);
    }

    private void notifyContactListFilterChanged() {
+164 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.contacts.common.list;

import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.TextView;

import com.android.contacts.common.R;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountType;

/**
 * Contact list filter parameters.
 */
public class ContactListFilterView extends LinearLayout {

    private static final String TAG = ContactListFilterView.class.getSimpleName();

    private ImageView mIcon;
    private TextView mAccountType;
    private TextView mAccountUserName;
    private RadioButton mRadioButton;
    private ContactListFilter mFilter;
    private boolean mSingleAccount;

    public ContactListFilterView(Context context) {
        super(context);
    }

    public ContactListFilterView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setContactListFilter(ContactListFilter filter) {
        mFilter = filter;
    }

    public ContactListFilter getContactListFilter() {
        return mFilter;
    }

    public void setSingleAccount(boolean flag) {
        this.mSingleAccount = flag;
    }

    @Override
    public void setActivated(boolean activated) {
        super.setActivated(activated);
        if (mRadioButton != null) {
            mRadioButton.setChecked(activated);
        } else {
            // We're guarding against null-pointer exceptions,
            // but otherwise this code is not expected to work
            // properly if the button hasn't been initialized.
            Log.wtf(TAG, "radio-button cannot be activated because it is null");
        }
        setContentDescription(generateContentDescription());
    }

    public boolean isChecked() {
        return mRadioButton.isChecked();
    }

    public void bindView(AccountTypeManager accountTypes) {
        if (mAccountType == null) {
            mIcon = (ImageView) findViewById(R.id.icon);
            mAccountType = (TextView) findViewById(R.id.accountType);
            mAccountUserName = (TextView) findViewById(R.id.accountUserName);
            mRadioButton = (RadioButton) findViewById(R.id.radioButton);
            mRadioButton.setChecked(isActivated());
        }

        if (mFilter == null) {
            mAccountType.setText(R.string.contactsList);
            return;
        }

        mAccountUserName.setVisibility(View.GONE);
        switch (mFilter.filterType) {
            case ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS: {
                bindView(0, R.string.list_filter_all_accounts);
                break;
            }
            case ContactListFilter.FILTER_TYPE_STARRED: {
                bindView(R.drawable.ic_menu_star_holo_light, R.string.list_filter_all_starred);
                break;
            }
            case ContactListFilter.FILTER_TYPE_CUSTOM: {
                bindView(R.drawable.ic_menu_settings_holo_light, R.string.list_filter_customize);
                break;
            }
            case ContactListFilter.FILTER_TYPE_WITH_PHONE_NUMBERS_ONLY: {
                bindView(0, R.string.list_filter_phones);
                break;
            }
            case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT: {
                bindView(0, R.string.list_filter_single);
                break;
            }
            case ContactListFilter.FILTER_TYPE_ACCOUNT: {
                mAccountUserName.setVisibility(View.VISIBLE);
                mIcon.setVisibility(View.VISIBLE);
                if (mFilter.icon != null) {
                    mIcon.setImageDrawable(mFilter.icon);
                } else {
                    mIcon.setImageResource(R.drawable.unknown_source);
                }
                final AccountType accountType =
                        accountTypes.getAccountType(mFilter.accountType, mFilter.dataSet);
                mAccountUserName.setText(mFilter.accountName);
                mAccountType.setText(accountType.getDisplayLabel(getContext()));
                break;
            }
        }
        setContentDescription(generateContentDescription());
    }

    private void bindView(int iconResource, int textResource) {
        if (iconResource != 0) {
            mIcon.setVisibility(View.VISIBLE);
            mIcon.setImageResource(iconResource);
        } else {
            mIcon.setVisibility(View.GONE);
        }

        mAccountType.setText(textResource);
    }

    String generateContentDescription() {
        final StringBuilder sb = new StringBuilder();
        if (!TextUtils.isEmpty(mAccountType.getText())) {
            sb.append(mAccountType.getText());
        }
        if (!TextUtils.isEmpty(mAccountUserName.getText())) {
            if (sb.length() > 0) {
                sb.append(" ");
            }
            sb.append(mAccountUserName.getText());
        }
        return getContext().getString(isActivated() ? R.string.account_filter_view_checked :
                R.string.account_filter_view_not_checked, sb.toString());
    }
}
+921 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading