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

Commit 758f5658 authored by Walter Jang's avatar Walter Jang
Browse files

Add groups to the side navigation bar

Just launch the old group details Activity for now.

Bug 18641067

Change-Id: I213c88213240d5281edfeda1bc5da9180506520b
parent f568b30b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -43,4 +43,7 @@

    <!-- An ID to be used for contents of a custom dialog so that its state be preserved -->
    <item type="id" name="custom_dialog_content" />

    <!-- Menu group ID for the contact groups -->
    <item type="id" name="menu_groups" />
</resources>
+5 −0
Original line number Diff line number Diff line
@@ -294,6 +294,11 @@
    <!-- The text displayed when the contacts list is empty while displaying all contacts [CHAR LIMIT=NONE] -->
    <string name="noContacts">No contacts</string>

    <!-- Group name menu item title when there is at least one group member. [CHAR LIMIT=NONE] -->
    <string name="group_name_menu_item">
        <xliff:g id="group_name">%s</xliff:g> (<xliff:g id="count">%d</xliff:g>)
    </string>

    <!-- The text displayed when the groups list is empty while displaying all groups [CHAR LIMIT=NONE] -->
    <string name="noGroups">No groups.</string>

+53 −16
Original line number Diff line number Diff line
@@ -36,9 +36,9 @@ import android.provider.ContactsContract.QuickContact;
import android.provider.Settings;
import android.support.design.widget.NavigationView;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
@@ -55,14 +55,13 @@ import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Toast;


import com.android.contacts.AppCompatContactsActivity;
import com.android.contacts.R;
import com.android.contacts.activities.ActionBarAdapter.TabState;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.activity.RequestPermissionsActivity;
import com.android.contacts.common.compat.TelecomManagerUtil;
import com.android.contacts.common.compat.BlockedNumberContractCompat;
import com.android.contacts.common.compat.TelecomManagerUtil;
import com.android.contacts.common.dialog.ClearFrequentsDialog;
import com.android.contacts.common.interactions.ImportExportDialogFragment;
import com.android.contacts.common.list.ContactEntryListFragment;
@@ -81,6 +80,10 @@ import com.android.contacts.common.util.ViewUtil;
import com.android.contacts.common.widget.FloatingActionButtonController;
import com.android.contacts.commonbind.ObjectFactory;
import com.android.contacts.editor.EditorIntents;
import com.android.contacts.group.GroupListItem;
import com.android.contacts.group.GroupUtil;
import com.android.contacts.group.GroupsFragment;
import com.android.contacts.group.GroupsFragment.GroupsListener;
import com.android.contacts.interactions.ContactDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction;
import com.android.contacts.interactions.ContactMultiDeletionInteraction.MultiContactDeleteListener;
@@ -114,6 +117,7 @@ public class PeopleActivity extends AppCompatContactsActivity implements
        ActionBarAdapter.Listener,
        DialogManager.DialogShowingViewActivity,
        ContactListFilterController.ContactListFilterListener,
        GroupsListener,
        ProviderStatusListener,
        MultiContactDeleteListener,
        JoinContactsListener,
@@ -152,6 +156,7 @@ public class PeopleActivity extends AppCompatContactsActivity implements
     */
    private MultiSelectContactsListFragment mAllFragment;
    private ContactTileListFragment mFavoritesFragment;
    private GroupsFragment mGroupsFragment;

    /** ViewPager for swipe */
    private ViewPager mTabPager;
@@ -160,6 +165,8 @@ public class PeopleActivity extends AppCompatContactsActivity implements
    private String[] mTabTitles;
    private final TabPagerListener mTabPagerListener = new TabPagerListener();

    private NavigationView mNavigationView;

    private boolean mEnableDebugMenuOptions;

    /**
@@ -340,10 +347,10 @@ public class PeopleActivity extends AppCompatContactsActivity implements
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        mNavigationView = (NavigationView) findViewById(R.id.nav_view);
        mNavigationView.setNavigationItemSelectedListener(this);

        final Menu menu = navigationView.getMenu();
        final Menu menu = mNavigationView.getMenu();
        if (HelpUtils.isHelpAndFeedbackAvailable()) {
            final MenuItem menuItem = menu.add(/* groupId */ R.id.misc, /* itemId */ R.id.nav_help,
                    /* order */ Menu.NONE, /* titleRes */ R.string.menu_help);
@@ -352,6 +359,7 @@ public class PeopleActivity extends AppCompatContactsActivity implements

        final String FAVORITE_TAG = "tab-pager-favorite";
        final String ALL_TAG = "tab-pager-all";
        final String GROUPS_TAG = "groups";

        // Create the fragments and add as children of the view pager.
        // The pager adapter will only change the visibility; it'll never create/destroy
@@ -363,13 +371,20 @@ public class PeopleActivity extends AppCompatContactsActivity implements
                fragmentManager.findFragmentByTag(FAVORITE_TAG);
        mAllFragment = (MultiSelectContactsListFragment)
                fragmentManager.findFragmentByTag(ALL_TAG);
        mGroupsFragment = (GroupsFragment)
                fragmentManager.findFragmentByTag(GROUPS_TAG);

        if (mFavoritesFragment == null) {
            mFavoritesFragment = new ContactTileListFragment();
            mAllFragment = new MultiSelectContactsListFragment();

            transaction.add(R.id.tab_pager, mFavoritesFragment, FAVORITE_TAG);

            mAllFragment = new MultiSelectContactsListFragment();
            transaction.add(R.id.tab_pager, mAllFragment, ALL_TAG);

            if (areGroupWritableAccountsAvailable()) {
                mGroupsFragment = new GroupsFragment();
                transaction.add(mGroupsFragment, GROUPS_TAG);
            }
        }

        mFavoritesFragment.setListener(mFavoritesFragmentListener);
@@ -377,10 +392,15 @@ public class PeopleActivity extends AppCompatContactsActivity implements
        mAllFragment.setOnContactListActionListener(new ContactBrowserActionListener());
        mAllFragment.setCheckBoxListListener(new CheckBoxListListener());

        if (areGroupWritableAccountsAvailable()) {
            mGroupsFragment.setListener(this);
        }

        // Hide all fragments for now.  We adjust visibility when we get onSelectedTabChanged()
        // from ActionBarAdapter.
        transaction.hide(mFavoritesFragment);
        transaction.hide(mAllFragment);
        // Groups fragment has no UI, no need to hide it

        transaction.commitAllowingStateLoss();
        fragmentManager.executePendingTransactions();
@@ -892,6 +912,26 @@ public class PeopleActivity extends AppCompatContactsActivity implements
        return TextUtils.getLayoutDirectionFromLocale(locale) == View.LAYOUT_DIRECTION_RTL;
    }

    @Override
    public void onGroupsLoaded(List<GroupListItem> groupListItems) {
        final Menu menu = mNavigationView.getMenu();
        menu.removeGroup(R.id.menu_groups);
        if (groupListItems == null || groupListItems.isEmpty()) {
            return;
        }
        for (GroupListItem groupListItem : groupListItems) {
            if (groupListItem.isFirstGroupInAccount()) {
                menu.addSubMenu(groupListItem.getAccountName());
            }
            final String title = groupListItem.getMemberCount() == 0 ? groupListItem.getTitle()
                    : getString(R.string.group_name_menu_item, groupListItem.getTitle(),
                            groupListItem.getMemberCount());
            final MenuItem menuItem =
                    menu.add(R.id.menu_groups, Menu.NONE, Menu.CATEGORY_SYSTEM, title);
            menuItem.setIntent(GroupUtil.createViewGroupIntent(this, groupListItem.getGroupId()));
        }
    }

    @Override
    public void onProviderStatusChange() {
        updateViewConfiguration(false);
@@ -1164,13 +1204,6 @@ public class PeopleActivity extends AppCompatContactsActivity implements
        }
    }

    private void makeMenuItemEnabled(Menu menu, int itemId, boolean visible) {
        final MenuItem item = menu.findItem(itemId);
        if (item != null) {
            item.setEnabled(visible);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDisableOptionItemSelected) {
@@ -1242,7 +1275,7 @@ public class PeopleActivity extends AppCompatContactsActivity implements
                return true;
            }
        }
        return false;
        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
@@ -1254,6 +1287,10 @@ public class PeopleActivity extends AppCompatContactsActivity implements
            startActivity(new Intent(this, ContactsPreferenceActivity.class));
        } else if (id == R.id.nav_help) {
            HelpUtils.launchHelpAndFeedbackForMainScreen(this);
        } else if (item.getIntent() != null) {
            ImplicitIntentsUtil.startActivityInApp(this, item.getIntent());
        } else {
            Log.w(TAG, "Unhandled navigation view item selection");
        }

        final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
+4 −36
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ public class GroupBrowseListAdapter extends BaseAdapter {
        if (mSelectedGroupUri == null && cursor != null && cursor.getCount() > 0) {
            GroupListItem firstItem = getItem(0);
            long groupId = (firstItem == null) ? 0 : firstItem.getGroupId();
            mSelectedGroupUri = getGroupUriFromId(groupId);
            mSelectedGroupUri = GroupUtil.getGroupUriFromId(groupId);
        }

        notifyDataSetChanged();
@@ -76,7 +76,7 @@ public class GroupBrowseListAdapter extends BaseAdapter {
        mCursor.moveToPosition(-1);
        while (mCursor.moveToNext()) {
            long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
            Uri uri = getGroupUriFromId(groupId);
            Uri uri = GroupUtil.getGroupUriFromId(groupId);
            if (mSelectedGroupUri.equals(uri)) {
                  return index;
            }
@@ -113,35 +113,7 @@ public class GroupBrowseListAdapter extends BaseAdapter {

    @Override
    public GroupListItem getItem(int position) {
        if (mCursor == null || mCursor.isClosed() || !mCursor.moveToPosition(position)) {
            return null;
        }
        String accountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
        String accountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
        String dataSet = mCursor.getString(GroupListLoader.DATA_SET);
        long groupId = mCursor.getLong(GroupListLoader.GROUP_ID);
        String title = mCursor.getString(GroupListLoader.TITLE);
        int memberCount = mCursor.getInt(GroupListLoader.MEMBER_COUNT);

        // Figure out if this is the first group for this account name / account type pair by
        // checking the previous entry. This is to determine whether or not we need to display an
        // account header in this item.
        int previousIndex = position - 1;
        boolean isFirstGroupInAccount = true;
        if (previousIndex >= 0 && mCursor.moveToPosition(previousIndex)) {
            String previousGroupAccountName = mCursor.getString(GroupListLoader.ACCOUNT_NAME);
            String previousGroupAccountType = mCursor.getString(GroupListLoader.ACCOUNT_TYPE);
            String previousGroupDataSet = mCursor.getString(GroupListLoader.DATA_SET);

            if (accountName.equals(previousGroupAccountName) &&
                    accountType.equals(previousGroupAccountType) &&
                    Objects.equal(dataSet, previousGroupDataSet)) {
                isFirstGroupInAccount = false;
            }
        }

        return new GroupListItem(accountName, accountType, dataSet, groupId, title,
                isFirstGroupInAccount, memberCount);
        return GroupUtil.getGroupListItem(mCursor, position);
    }

    @Override
@@ -180,7 +152,7 @@ public class GroupBrowseListAdapter extends BaseAdapter {
        }

        // Bind the group data
        Uri groupUri = getGroupUriFromId(entry.getGroupId());
        Uri groupUri = GroupUtil.getGroupUriFromId(entry.getGroupId());
        String memberCountString = mContext.getResources().getQuantityString(
                R.plurals.group_list_num_contacts_in_group, entry.getMemberCount(),
                entry.getMemberCount());
@@ -201,10 +173,6 @@ public class GroupBrowseListAdapter extends BaseAdapter {
        viewCache.accountName.setText(entry.getAccountName());
    }

    private static Uri getGroupUriFromId(long groupId) {
        return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
    }

    /**
     * Cache of the children views of a contact detail entry represented by a
     * {@link GroupListItem}
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.group;

import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract.Groups;

import com.android.contacts.GroupListLoader;
import com.android.contacts.activities.GroupDetailActivity;
import com.google.common.base.Objects;

/**
 * Group utility methods.
 */
public final class GroupUtil {

    private GroupUtil() {
    }

    /** Returns a {@link GroupListItem} read from the given cursor and position. */
    static GroupListItem getGroupListItem(Cursor cursor, int position) {
        if (cursor == null || cursor.isClosed() || !cursor.moveToPosition(position)) {
            return null;
        }
        String accountName = cursor.getString(GroupListLoader.ACCOUNT_NAME);
        String accountType = cursor.getString(GroupListLoader.ACCOUNT_TYPE);
        String dataSet = cursor.getString(GroupListLoader.DATA_SET);
        long groupId = cursor.getLong(GroupListLoader.GROUP_ID);
        String title = cursor.getString(GroupListLoader.TITLE);
        int memberCount = cursor.getInt(GroupListLoader.MEMBER_COUNT);

        // Figure out if this is the first group for this account name / account type pair by
        // checking the previous entry. This is to determine whether or not we need to display an
        // account header in this item.
        int previousIndex = position - 1;
        boolean isFirstGroupInAccount = true;
        if (previousIndex >= 0 && cursor.moveToPosition(previousIndex)) {
            String previousGroupAccountName = cursor.getString(GroupListLoader.ACCOUNT_NAME);
            String previousGroupAccountType = cursor.getString(GroupListLoader.ACCOUNT_TYPE);
            String previousGroupDataSet = cursor.getString(GroupListLoader.DATA_SET);

            if (accountName.equals(previousGroupAccountName) &&
                    accountType.equals(previousGroupAccountType) &&
                    Objects.equal(dataSet, previousGroupDataSet)) {
                isFirstGroupInAccount = false;
            }
        }

        return new GroupListItem(accountName, accountType, dataSet, groupId, title,
                isFirstGroupInAccount, memberCount);
    }

    /** Returns an Intent to view the details of the group identified by the given Uri. */
    public static Intent createViewGroupIntent(Context context, long groupId) {
        final Intent intent = new Intent(context, GroupDetailActivity.class);
        intent.setData(getGroupUriFromId(groupId));
        return intent;
    }

    /** TODO: Make it private after {@link GroupBrowseListAdapter} is removed. */
    static Uri getGroupUriFromId(long groupId) {
        return ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
    }
}
 No newline at end of file
Loading