From 73b51d5771b31c932a589abc9bb0fe64c52fe102 Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Fri, 8 Dec 2017 20:52:56 -0800 Subject: Implemented adding a new favorites contact flow NUI. This change consists of mainly 3 things: - Update contacts fragment to meet AddFavoriteActivity requirements - Implement AddFavoriteActivity - Passing the contact back to SpeedDialFragment Bug: 36841782 Test: SpeedDialIntegrationTest PiperOrigin-RevId: 178461265 Change-Id: Ib3a13eae311acf6ce10a94df4f2c95b9af120cff --- java/com/android/dialer/app/DialtactsActivity.java | 15 ++- .../dialer/app/list/DialtactsPagerAdapter.java | 4 +- .../dialer/contactsfragment/ContactViewHolder.java | 31 ++---- .../dialer/contactsfragment/ContactsAdapter.java | 20 ++-- .../contactsfragment/ContactsCursorLoader.java | 57 +++++++--- .../dialer/contactsfragment/ContactsFragment.java | 120 ++++++++++++--------- .../databasepopulator/ContactsPopulator.java | 13 +++ .../dialer/speeddial/AddFavoriteActivity.java | 109 +++++++++++++++++++ .../android/dialer/speeddial/AndroidManifest.xml | 13 ++- .../android/dialer/speeddial/SpeedDialCursor.java | 4 - .../dialer/speeddial/SpeedDialFragment.java | 40 +++---- .../speeddial/res/layout/add_favorite_activity.xml | 21 ++++ .../speeddial/res/menu/add_favorite_menu.xml | 24 +++++ .../dialer/speeddial/res/values/strings.xml | 9 +- 14 files changed, 352 insertions(+), 128 deletions(-) create mode 100644 java/com/android/dialer/speeddial/AddFavoriteActivity.java create mode 100644 java/com/android/dialer/speeddial/res/layout/add_favorite_activity.xml create mode 100644 java/com/android/dialer/speeddial/res/menu/add_favorite_menu.xml (limited to 'java') diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java index 2d82b6f33..48796dba3 100644 --- a/java/com/android/dialer/app/DialtactsActivity.java +++ b/java/com/android/dialer/app/DialtactsActivity.java @@ -32,6 +32,7 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.Trace; import android.provider.CallLog.Calls; +import android.provider.ContactsContract.QuickContact; import android.speech.RecognizerIntent; import android.support.annotation.MainThread; import android.support.annotation.NonNull; @@ -59,6 +60,7 @@ import android.view.animation.AnimationUtils; import android.widget.AbsListView.OnScrollListener; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; @@ -101,6 +103,7 @@ import com.android.dialer.common.concurrent.ThreadUtil; import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.constants.ActivityRequestCodes; import com.android.dialer.contactsfragment.ContactsFragment; +import com.android.dialer.contactsfragment.ContactsFragment.OnContactSelectedListener; import com.android.dialer.database.Database; import com.android.dialer.database.DialerDatabaseHelper; import com.android.dialer.dialpadview.DialpadFragment; @@ -109,6 +112,7 @@ import com.android.dialer.dialpadview.DialpadFragment.LastOutgoingCallCallback; import com.android.dialer.interactions.PhoneNumberInteraction; import com.android.dialer.interactions.PhoneNumberInteraction.InteractionErrorCode; import com.android.dialer.logging.DialerImpression; +import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; import com.android.dialer.logging.LoggingBindings; import com.android.dialer.logging.ScreenEvent; @@ -166,7 +170,8 @@ public class DialtactsActivity extends TransactionSafeActivity PhoneNumberInteraction.DisambigDialogDismissedListener, ActivityCompat.OnRequestPermissionsResultCallback, DialpadListener, - SearchFragmentListener { + SearchFragmentListener, + OnContactSelectedListener { public static final boolean DEBUG = false; @VisibleForTesting public static final String TAG_DIALPAD_FRAGMENT = "dialpad"; @@ -1695,6 +1700,14 @@ public class DialtactsActivity extends TransactionSafeActivity return mPreviouslySelectedTabIndex; } + @Override + public void onContactSelected(ImageView photo, Uri contactUri, long contactId) { + Logger.get(this) + .logInteraction(InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CONTACTS_FRAGMENT_ITEM); + QuickContact.showQuickContact( + this, photo, contactUri, QuickContact.MODE_LARGE, null /* excludeMimes */); + } + /** Popup menu accessible from the search bar */ protected class OptionsPopupMenu extends PopupMenu { diff --git a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java index 484ab0b9e..d27293244 100644 --- a/java/com/android/dialer/app/list/DialtactsPagerAdapter.java +++ b/java/com/android/dialer/app/list/DialtactsPagerAdapter.java @@ -28,7 +28,6 @@ import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.configprovider.ConfigProviderBindings; import com.android.dialer.contactsfragment.ContactsFragment; -import com.android.dialer.contactsfragment.ContactsFragment.ClickAction; import com.android.dialer.contactsfragment.ContactsFragment.Header; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.speeddial.SpeedDialFragment; @@ -108,8 +107,7 @@ public class DialtactsPagerAdapter extends FragmentPagerAdapter { case TAB_INDEX_ALL_CONTACTS: if (useNewContactsTab) { if (contactsFragment == null) { - contactsFragment = - ContactsFragment.newInstance(Header.ADD_CONTACT, ClickAction.OPEN_CONTACT_CARD); + contactsFragment = ContactsFragment.newInstance(Header.ADD_CONTACT); } return contactsFragment; } else { diff --git a/java/com/android/dialer/contactsfragment/ContactViewHolder.java b/java/com/android/dialer/contactsfragment/ContactViewHolder.java index 0597c2a7e..2730c0d38 100644 --- a/java/com/android/dialer/contactsfragment/ContactViewHolder.java +++ b/java/com/android/dialer/contactsfragment/ContactViewHolder.java @@ -18,7 +18,6 @@ package com.android.dialer.contactsfragment; import android.content.Context; import android.net.Uri; -import android.provider.ContactsContract.QuickContact; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.View; @@ -26,7 +25,7 @@ import android.view.View.OnClickListener; import android.widget.QuickContactBadge; import android.widget.TextView; import com.android.dialer.common.Assert; -import com.android.dialer.contactsfragment.ContactsFragment.ClickAction; +import com.android.dialer.contactsfragment.ContactsFragment.OnContactSelectedListener; import com.android.dialer.logging.InteractionEvent; import com.android.dialer.logging.Logger; @@ -37,20 +36,20 @@ final class ContactViewHolder extends RecyclerView.ViewHolder implements OnClick private final TextView name; private final QuickContactBadge photo; private final Context context; - private final @ClickAction int clickAction; + private final OnContactSelectedListener onContactSelectedListener; private String headerText; private Uri contactUri; + private long contactId; - ContactViewHolder(View itemView, @ClickAction int clickAction) { + ContactViewHolder(View itemView, OnContactSelectedListener onContactSelectedListener) { super(itemView); - Assert.checkArgument(clickAction != ClickAction.INVALID, "Invalid click action."); + this.onContactSelectedListener = Assert.isNotNull(onContactSelectedListener); context = itemView.getContext(); itemView.findViewById(R.id.click_target).setOnClickListener(this); header = itemView.findViewById(R.id.header); name = itemView.findViewById(R.id.contact_name); photo = itemView.findViewById(R.id.photo); - this.clickAction = clickAction; } /** @@ -61,9 +60,11 @@ final class ContactViewHolder extends RecyclerView.ViewHolder implements OnClick * @param contactUri to be shown by the contact card on photo click. * @param showHeader if header view should be shown {@code True}, {@code False} otherwise. */ - public void bind(String headerText, String displayName, Uri contactUri, boolean showHeader) { + public void bind( + String headerText, String displayName, Uri contactUri, long contactId, boolean showHeader) { Assert.checkArgument(!TextUtils.isEmpty(displayName)); this.contactUri = contactUri; + this.contactId = contactId; this.headerText = headerText; name.setText(displayName); @@ -89,20 +90,6 @@ final class ContactViewHolder extends RecyclerView.ViewHolder implements OnClick @Override public void onClick(View v) { - switch (clickAction) { - case ClickAction.OPEN_CONTACT_CARD: - Logger.get(context) - .logInteraction(InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_CONTACTS_FRAGMENT_ITEM); - QuickContact.showQuickContact( - photo.getContext(), - photo, - contactUri, - QuickContact.MODE_LARGE, - null /* excludeMimes */); - break; - case ClickAction.INVALID: - default: - throw Assert.createIllegalStateFailException("Invalid click action."); - } + onContactSelectedListener.onContactSelected(photo, contactUri, contactId); } } diff --git a/java/com/android/dialer/contactsfragment/ContactsAdapter.java b/java/com/android/dialer/contactsfragment/ContactsAdapter.java index 8f2120cd7..44abe29da 100644 --- a/java/com/android/dialer/contactsfragment/ContactsAdapter.java +++ b/java/com/android/dialer/contactsfragment/ContactsAdapter.java @@ -29,8 +29,8 @@ import android.view.ViewGroup; import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.contactphoto.ContactPhotoManager; -import com.android.dialer.contactsfragment.ContactsFragment.ClickAction; import com.android.dialer.contactsfragment.ContactsFragment.Header; +import com.android.dialer.contactsfragment.ContactsFragment.OnContactSelectedListener; import com.android.dialer.lettertile.LetterTileDrawable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -50,7 +50,7 @@ final class ContactsAdapter extends RecyclerView.Adapter holderMap = new ArrayMap<>(); private final Context context; private final @Header int header; - private final @ClickAction int clickAction; + private final OnContactSelectedListener onContactSelectedListener; // List of contact sublist headers private String[] headers = new String[0]; @@ -59,10 +59,11 @@ final class ContactsAdapter extends RecyclerView.Adapter *
  • {@link Header#ADD_CONTACT} to insert a header that allows users to add a contact - *
  • {@link ClickAction#OPEN_CONTACT_CARD} to open contact cards on click + *
  • Open contact cards on click * * * And for the add favorite contact screen we might use: * *
      *
    • {@link Header#NONE} so that all rows are contacts (i.e. no header inserted) - *
    • {@link ClickAction#SET_RESULT_AND_FINISH} to send a selected contact to the previous - * activity. + *
    • Send a selected contact to the parent activity. *
    * * @param header determines the type of header inserted at position 0 in the contacts list - * @param clickAction defines the on click actions on rows that represent contacts */ - public static ContactsFragment newInstance(@Header int header, @ClickAction int clickAction) { - Assert.checkArgument(clickAction != ClickAction.INVALID, "Invalid click action"); + public static ContactsFragment newInstance(@Header int header) { ContactsFragment fragment = new ContactsFragment(); Bundle args = new Bundle(); args.putInt(EXTRA_HEADER, header); - args.putInt(EXTRA_CLICK_ACTION, clickAction); + fragment.setArguments(args); + return fragment; + } + + /** + * Returns {@link ContactsFragment} with a list of contacts such that: + * + *
      + *
    • Each contact has a phone number + *
    • Contacts are filterable via {@link #updateQuery(String)} + *
    • There is no list header (i.e. {@link Header#NONE} + *
    • Clicking on a contact notifies the parent activity via {@link + * OnContactSelectedListener#onContactSelected(ImageView, Uri, long)}. + *
    + */ + public static ContactsFragment newAddFavoritesInstance() { + ContactsFragment fragment = new ContactsFragment(); + Bundle args = new Bundle(); + args.putInt(EXTRA_HEADER, Header.NONE); + args.putBoolean(EXTRA_HAS_PHONE_NUMBERS, true); fragment.setArguments(args); return fragment; } @@ -152,7 +158,21 @@ public class ContactsFragment extends Fragment contactsPrefs = new ContactsPreferences(getContext()); contactsPrefs.registerChangeListener(this); header = getArguments().getInt(EXTRA_HEADER); - clickAction = getArguments().getInt(EXTRA_CLICK_ACTION); + hasPhoneNumbers = getArguments().getBoolean(EXTRA_HAS_PHONE_NUMBERS); + } + + @Override + public void onStart() { + super.onStart(); + PermissionsUtil.registerPermissionReceiver( + getActivity(), readContactsPermissionGrantedReceiver, READ_CONTACTS); + } + + @Override + public void onStop() { + PermissionsUtil.unregisterPermissionReceiver( + getActivity(), readContactsPermissionGrantedReceiver); + super.onStop(); } @Nullable @@ -163,7 +183,9 @@ public class ContactsFragment extends Fragment fastScroller = view.findViewById(R.id.fast_scroller); anchoredHeader = view.findViewById(R.id.header); recyclerView = view.findViewById(R.id.recycler_view); - adapter = new ContactsAdapter(getContext(), header, clickAction); + adapter = + new ContactsAdapter( + getContext(), header, FragmentUtils.getParent(this, OnContactSelectedListener.class)); recyclerView.setAdapter(adapter); manager = new LinearLayoutManager(getContext()) { @@ -208,15 +230,14 @@ public class ContactsFragment extends Fragment /** @return a loader according to sort order and display order. */ @Override public Loader onCreateLoader(int id, Bundle args) { - boolean sortOrderPrimary = - (contactsPrefs.getSortOrder() == ContactsPreferences.SORT_ORDER_PRIMARY); - boolean displayOrderPrimary = - (contactsPrefs.getDisplayOrder() == ContactsPreferences.DISPLAY_ORDER_PRIMARY); - - String sortKey = sortOrderPrimary ? Contacts.SORT_KEY_PRIMARY : Contacts.SORT_KEY_ALTERNATIVE; - return displayOrderPrimary - ? ContactsCursorLoader.createInstanceDisplayNamePrimary(getContext(), sortKey) - : ContactsCursorLoader.createInstanceDisplayNameAlternative(getContext(), sortKey); + ContactsCursorLoader cursorLoader = new ContactsCursorLoader(getContext(), hasPhoneNumbers); + cursorLoader.setQuery(query); + return cursorLoader; + } + + public void updateQuery(String query) { + this.query = query; + getLoaderManager().restartLoader(0, null, this); } @Override @@ -266,10 +287,13 @@ public class ContactsFragment extends Fragment } String anchoredHeaderString = adapter.getHeaderString(firstCompletelyVisible); - FragmentUtils.getParentUnsafe(this, OnContactsListScrolledListener.class) - .onContactsListScrolled( - recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING - || fastScroller.isDragStarted()); + OnContactsListScrolledListener listener = + FragmentUtils.getParent(this, OnContactsListScrolledListener.class); + if (listener != null) { + listener.onContactsListScrolled( + recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING + || fastScroller.isDragStarted()); + } // If the user swipes to the top of the list very quickly, there is some strange behavior // between this method updating headers and adapter#onBindViewHolder updating headers. @@ -331,17 +355,15 @@ public class ContactsFragment extends Fragment } } - @Override - public void onStart() { - super.onStart(); - PermissionsUtil.registerPermissionReceiver( - getActivity(), readContactsPermissionGrantedReceiver, READ_CONTACTS); + /** Listener for contacts list scroll state. */ + public interface OnContactsListScrolledListener { + void onContactsListScrolled(boolean isDragging); } - @Override - public void onStop() { - PermissionsUtil.unregisterPermissionReceiver( - getActivity(), readContactsPermissionGrantedReceiver); - super.onStop(); + /** Listener to notify parents when a contact is selected. */ + public interface OnContactSelectedListener { + + /** Called when a contact is selected in {@link ContactsFragment}. */ + void onContactSelected(ImageView photo, Uri contactUri, long contactId); } } diff --git a/java/com/android/dialer/databasepopulator/ContactsPopulator.java b/java/com/android/dialer/databasepopulator/ContactsPopulator.java index 79492e9d3..f22552db7 100644 --- a/java/com/android/dialer/databasepopulator/ContactsPopulator.java +++ b/java/com/android/dialer/databasepopulator/ContactsPopulator.java @@ -147,6 +147,19 @@ public final class ContactsPopulator { } } + @WorkerThread + public static void populateSpeedDialTestContacts(@NonNull Context context) { + Assert.isWorkerThread(); + ArrayList operations = new ArrayList<>(); + addContact(SIMPLE_CONTACTS[0], operations); + addContact(SIMPLE_CONTACTS[5], operations); + try { + context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations); + } catch (RemoteException | OperationApplicationException e) { + Assert.fail("error adding contacts: " + e); + } + } + @WorkerThread public static void populateContacts(@NonNull Context context) { populateContacts(context, false); diff --git a/java/com/android/dialer/speeddial/AddFavoriteActivity.java b/java/com/android/dialer/speeddial/AddFavoriteActivity.java new file mode 100644 index 000000000..eea6e840e --- /dev/null +++ b/java/com/android/dialer/speeddial/AddFavoriteActivity.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2017 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.speeddial; + +import android.content.ContentValues; +import android.net.Uri; +import android.os.Bundle; +import android.provider.ContactsContract.Contacts; +import android.support.annotation.Nullable; +import android.support.annotation.WorkerThread; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.ImageView; +import com.android.dialer.common.Assert; +import com.android.dialer.common.concurrent.DialerExecutorComponent; +import com.android.dialer.contactsfragment.ContactsFragment; +import com.android.dialer.contactsfragment.ContactsFragment.OnContactSelectedListener; + +/** + * Activity for selecting a single contact and adding it to favorites. + * + *

    Contacts are displayed using {@link ContactsFragment}. Contacts are searchable via search bar + * in the toolbar. When a contact is selected, it's uri is passed back in the result data. + */ +public class AddFavoriteActivity extends AppCompatActivity implements OnContactSelectedListener { + + private ContactsFragment contactsFragment; + + @Override + protected void onCreate(@Nullable Bundle bundle) { + super.onCreate(bundle); + setContentView(R.layout.add_favorite_activity); + contactsFragment = ContactsFragment.newAddFavoritesInstance(); + getFragmentManager() + .beginTransaction() + .add(R.id.add_favorite_container, contactsFragment, null) + .commit(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.add_favorite_menu, menu); + + MenuItem searchItem = menu.findItem(R.id.action_search); + SearchView searchView = (SearchView) searchItem.getActionView(); + searchView.setOnQueryTextListener( + new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String query) { + if (!searchView.isIconified()) { + searchView.setIconified(true); + } + searchItem.collapseActionView(); + return false; + } + + @Override + public boolean onQueryTextChange(String s) { + contactsFragment.updateQuery(s); + return false; + } + }); + return true; + } + + @Override + public void onContactSelected(ImageView photo, Uri contactUri, long contactId) { + DialerExecutorComponent.get(this) + .dialerExecutorFactory() + .createUiTaskBuilder( + getFragmentManager(), "mark_contact_favorite", this::markContactStarred) + .onSuccess(output -> finish()) + .onFailure(this::onContactStarredFailed) + .build() + .executeParallel(contactId); + } + + @WorkerThread + private int markContactStarred(long contactId) { + // TODO(calderwoodra): For now, we will just mark contacts as starred. This means that contacts + // will only be able to exist once in favorites until we implement multiple contact avenues. + ContentValues contentValues = new ContentValues(); + contentValues.put(Contacts.STARRED, 1); + + String where = Contacts._ID + " = ?"; + String[] selectionArgs = new String[] {Long.toString(contactId)}; + return getContentResolver().update(Contacts.CONTENT_URI, contentValues, where, selectionArgs); + } + + private void onContactStarredFailed(Throwable throwable) { + throw Assert.createAssertionFailException(throwable.getMessage()); + } +} diff --git a/java/com/android/dialer/speeddial/AndroidManifest.xml b/java/com/android/dialer/speeddial/AndroidManifest.xml index f4f0d82eb..99ab12c4b 100644 --- a/java/com/android/dialer/speeddial/AndroidManifest.xml +++ b/java/com/android/dialer/speeddial/AndroidManifest.xml @@ -13,4 +13,15 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> - + + + + + + \ No newline at end of file diff --git a/java/com/android/dialer/speeddial/SpeedDialCursor.java b/java/com/android/dialer/speeddial/SpeedDialCursor.java index 552fab175..1208daefd 100644 --- a/java/com/android/dialer/speeddial/SpeedDialCursor.java +++ b/java/com/android/dialer/speeddial/SpeedDialCursor.java @@ -64,10 +64,6 @@ final class SpeedDialCursor extends MergeCursor { strequentCursor.moveToPosition(-1); while (strequentCursor.moveToNext()) { - if (strequentCursor.getInt(StrequentContactsCursorLoader.PHONE_IS_SUPER_PRIMARY) != 0) { - continue; - } - if (strequentCursor.getPosition() != 0) { long contactId = strequentCursor.getLong(StrequentContactsCursorLoader.PHONE_CONTACT_ID); int position = strequentCursor.getPosition(); diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index 65e542cd4..08861dae9 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -18,10 +18,10 @@ package com.android.dialer.speeddial; import android.app.Fragment; import android.app.LoaderManager.LoaderCallbacks; +import android.content.Intent; import android.content.Loader; import android.database.Cursor; import android.os.Bundle; -import android.provider.ContactsContract.Contacts; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -35,7 +35,16 @@ import com.android.dialer.speeddial.FavoritesViewHolder.FavoriteContactsListener import com.android.dialer.speeddial.HeaderViewHolder.SpeedDialHeaderListener; import com.android.dialer.speeddial.SuggestionViewHolder.SuggestedContactsListener; -/** Favorites fragment. Contents TBD. TODO(calderwoodra) */ +/** + * Fragment for displaying: + * + *

      + *
    • Favorite/Starred contacts + *
    • Suggested contacts + *
    + * + *

    Suggested contacts built from {@link android.provider.ContactsContract#STREQUENT_PHONE_ONLY}. + */ public class SpeedDialFragment extends Fragment { private static final int STREQUENT_CONTACTS_LOADER_ID = 1; @@ -73,16 +82,16 @@ public class SpeedDialFragment extends Fragment { } @Override - public void onPause() { - super.onPause(); - loaderCallback.unregisterContentObserver(); + public void onResume() { + super.onResume(); + getLoaderManager().restartLoader(STREQUENT_CONTACTS_LOADER_ID, null, loaderCallback); } - private static class SpeedDialFragmentHeaderListener implements SpeedDialHeaderListener { + private class SpeedDialFragmentHeaderListener implements SpeedDialHeaderListener { @Override public void onAddFavoriteClicked() { - // TODO(calderwoodra): implement add favorite screen + startActivity(new Intent(getContext(), AddFavoriteActivity.class)); } } @@ -123,8 +132,6 @@ public class SpeedDialFragment extends Fragment { */ private class SpeedDialFragmentLoaderCallback implements LoaderCallbacks { - private StrequentContactsCursorLoader cursorLoader; - @Override public Loader onCreateLoader(int id, Bundle args) { if (id == STREQUENT_CONTACTS_LOADER_ID) { @@ -135,24 +142,9 @@ public class SpeedDialFragment extends Fragment { @Override public void onLoadFinished(Loader loader, Cursor data) { - cursorLoader = (StrequentContactsCursorLoader) loader; - // Since the original cursor we queried against was modified and closed, we need to register a - // new content observer in order to get updates on changes to our contacts. - getContext() - .getContentResolver() - .registerContentObserver( - Contacts.CONTENT_STREQUENT_URI, - true /* notifyForDescendants*/, - cursorLoader.getContentObserver()); adapter.setCursor((SpeedDialCursor) data); } - public void unregisterContentObserver() { - getContext() - .getContentResolver() - .unregisterContentObserver(cursorLoader.getContentObserver()); - } - @Override public void onLoaderReset(Loader loader) { adapter.setCursor(null); diff --git a/java/com/android/dialer/speeddial/res/layout/add_favorite_activity.xml b/java/com/android/dialer/speeddial/res/layout/add_favorite_activity.xml new file mode 100644 index 000000000..4df2f29b4 --- /dev/null +++ b/java/com/android/dialer/speeddial/res/layout/add_favorite_activity.xml @@ -0,0 +1,21 @@ + + + \ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/menu/add_favorite_menu.xml b/java/com/android/dialer/speeddial/res/menu/add_favorite_menu.xml new file mode 100644 index 000000000..b11c7f5d6 --- /dev/null +++ b/java/com/android/dialer/speeddial/res/menu/add_favorite_menu.xml @@ -0,0 +1,24 @@ + + +

    + + \ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/values/strings.xml b/java/com/android/dialer/speeddial/res/values/strings.xml index f814ed6d4..d64d03575 100644 --- a/java/com/android/dialer/speeddial/res/values/strings.xml +++ b/java/com/android/dialer/speeddial/res/values/strings.xml @@ -15,12 +15,15 @@ ~ limitations under the License --> - + Favorites - + Suggestions - + Add + + + Add Favorite \ No newline at end of file -- cgit v1.2.3