summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcalderwoodra <calderwoodra@google.com>2018-04-18 16:48:57 -0700
committerCopybara-Service <copybara-piper@google.com>2018-04-18 16:51:32 -0700
commit0388bfc9717dbf1d67ed4c14f34aa5414a08b39c (patch)
treedc277edb839034daa01f46b4ae597e63017dbe64
parent560eb125b437fef71e624327a024853dd9bc06ea (diff)
Implement adding favorites.
This change deletes the AddFavoritesActivity in favor of the activity provided to us by the Intent.ACTION_PICK intent. Bug: 36841782 Test: SpeedDialUiItemLoaderTest PiperOrigin-RevId: 193439522 Change-Id: Ie297abd2307c727d746f26ba99961de116636dc4
-rw-r--r--java/com/android/dialer/constants/ActivityRequestCodes.java5
-rw-r--r--java/com/android/dialer/speeddial/AddFavoriteActivity.java109
-rw-r--r--java/com/android/dialer/speeddial/AndroidManifest.xml13
-rw-r--r--java/com/android/dialer/speeddial/SpeedDialFragment.java38
-rw-r--r--java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java60
5 files changed, 99 insertions, 126 deletions
diff --git a/java/com/android/dialer/constants/ActivityRequestCodes.java b/java/com/android/dialer/constants/ActivityRequestCodes.java
index 7fd619ba9..c96fe9ed1 100644
--- a/java/com/android/dialer/constants/ActivityRequestCodes.java
+++ b/java/com/android/dialer/constants/ActivityRequestCodes.java
@@ -37,4 +37,9 @@ public final class ActivityRequestCodes {
/** Request code for {@link com.android.dialer.calldetails.OldCallDetailsActivity} intent. */
public static final int DIALTACTS_CALL_DETAILS = 4;
+
+ /**
+ * Request code for {@link com.android.dialer.speeddial.SpeedDialFragment} contact picker intent.
+ */
+ public static final int SPEED_DIAL_ADD_FAVORITE = 5;
}
diff --git a/java/com/android/dialer/speeddial/AddFavoriteActivity.java b/java/com/android/dialer/speeddial/AddFavoriteActivity.java
deleted file mode 100644
index eea6e840e..000000000
--- a/java/com/android/dialer/speeddial/AddFavoriteActivity.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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.
- *
- * <p>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 99ab12c4b..913e5007a 100644
--- a/java/com/android/dialer/speeddial/AndroidManifest.xml
+++ b/java/com/android/dialer/speeddial/AndroidManifest.xml
@@ -13,15 +13,4 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.dialer.speeddial">
-
- <application android:theme="@style/Theme.AppCompat">
- <activity
- android:name="com.android.dialer.speeddial.AddFavoriteActivity"
- android:label="@string/add_favorite_activity_title"
- android:exported="false"
- android:theme="@style/DialtactsTheme"/>
- </application>
-</manifest> \ No newline at end of file
+<manifest package="com.android.dialer.speeddial"/>
diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java
index 004588ef4..52d7b7fc9 100644
--- a/java/com/android/dialer/speeddial/SpeedDialFragment.java
+++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java
@@ -18,8 +18,10 @@ package com.android.dialer.speeddial;
import android.content.Intent;
import android.os.Bundle;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
+import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
@@ -73,6 +75,12 @@ public class SpeedDialFragment extends Fragment {
private SpeedDialLayoutManager layoutManager;
private SupportUiListener<ImmutableList<SpeedDialUiItem>> speedDialLoaderListener;
+ /**
+ * We update the UI every time the fragment is resumed. This boolean suppresses that functionality
+ * once per onResume call.
+ */
+ private boolean updateSpeedDialItemsOnResume = true;
+
public static SpeedDialFragment newInstance() {
return new SpeedDialFragment();
}
@@ -123,6 +131,11 @@ public class SpeedDialFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
+ if (!updateSpeedDialItemsOnResume) {
+ updateSpeedDialItemsOnResume = true;
+ return;
+ }
+
speedDialLoaderListener.listen(
getContext(),
UiItemLoaderComponent.get(getContext()).speedDialUiItemLoader().loadSpeedDialUiItems(),
@@ -138,11 +151,34 @@ public class SpeedDialFragment extends Fragment {
});
}
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == ActivityRequestCodes.SPEED_DIAL_ADD_FAVORITE) {
+ if (resultCode == AppCompatActivity.RESULT_OK && data.getData() != null) {
+ updateSpeedDialItemsOnResume = false;
+ speedDialLoaderListener.listen(
+ getContext(),
+ UiItemLoaderComponent.get(getContext())
+ .speedDialUiItemLoader()
+ .starContact(data.getData()),
+ speedDialUiItems -> {
+ adapter.setSpeedDialUiItems(speedDialUiItems);
+ // TODO(calderwoodra): Use DiffUtil to properly update and animate the change
+ adapter.notifyDataSetChanged();
+ },
+ throwable -> {
+ throw new RuntimeException(throwable);
+ });
+ }
+ }
+ }
+
private class SpeedDialFragmentHeaderListener implements SpeedDialHeaderListener {
@Override
public void onAddFavoriteClicked() {
- startActivity(new Intent(getContext(), AddFavoriteActivity.class));
+ Intent intent = new Intent(Intent.ACTION_PICK, Phone.CONTENT_URI);
+ startActivityForResult(intent, ActivityRequestCodes.SPEED_DIAL_ADD_FAVORITE);
}
}
diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
index 9a027de71..9ea84eca2 100644
--- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
+++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java
@@ -17,6 +17,7 @@
package com.android.dialer.speeddial.loader;
import android.annotation.TargetApi;
+import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
@@ -97,14 +98,61 @@ public final class SpeedDialUiItemLoader {
* from {@link Contacts#STREQUENT_PHONE_ONLY}.
*/
public ListenableFuture<ImmutableList<SpeedDialUiItem>> loadSpeedDialUiItems() {
- return dialerFutureSerializer.submitAsync(
- () -> backgroundExecutor.submit(this::doInBackground), backgroundExecutor);
+ return dialerFutureSerializer.submit(this::loadSpeedDialUiItemsInternal, backgroundExecutor);
+ }
+
+ /**
+ * Takes a contact uri from {@link Phone#CONTENT_URI} and updates {@link Phone#STARRED} to be
+ * true, if it isn't already or Inserts the contact into the {@link SpeedDialEntryDatabaseHelper}
+ */
+ public ListenableFuture<ImmutableList<SpeedDialUiItem>> starContact(Uri contactUri) {
+ return dialerFutureSerializer.submit(
+ () -> insertNewContactEntry(contactUri), backgroundExecutor);
+ }
+
+ @WorkerThread
+ private ImmutableList<SpeedDialUiItem> insertNewContactEntry(Uri contactUri) {
+ Assert.isWorkerThread();
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(contactUri, SpeedDialUiItem.PHONE_PROJECTION, null, null, null)) {
+ if (cursor == null) {
+ LogUtil.e("SpeedDialUiItemLoader.insertNewContactEntry", "Cursor was null");
+ return loadSpeedDialUiItemsInternal();
+ }
+ Assert.checkArgument(cursor.moveToFirst(), "Cursor should never be empty");
+ SpeedDialUiItem item = SpeedDialUiItem.fromCursor(cursor);
+
+ // Star the contact if it isn't starred already, then return.
+ if (!item.isStarred()) {
+ ContentValues values = new ContentValues();
+ values.put(Phone.STARRED, "1");
+ appContext
+ .getContentResolver()
+ .update(
+ Contacts.CONTENT_URI,
+ values,
+ Contacts._ID + " = ?",
+ new String[] {Long.toString(item.contactId())});
+ }
+
+ // Insert a new entry into the SpeedDialEntry database
+ getSpeedDialEntryDao()
+ .insert(
+ SpeedDialEntry.builder()
+ .setLookupKey(item.lookupKey())
+ .setContactId(item.contactId())
+ .setDefaultChannel(item.defaultChannel())
+ .build());
+ }
+ return loadSpeedDialUiItemsInternal();
}
@WorkerThread
- private ImmutableList<SpeedDialUiItem> doInBackground() {
+ private ImmutableList<SpeedDialUiItem> loadSpeedDialUiItemsInternal() {
Assert.isWorkerThread();
- SpeedDialEntryDao db = new SpeedDialEntryDatabaseHelper(appContext);
+ SpeedDialEntryDao db = getSpeedDialEntryDao();
// This is the list of contacts that we will display to the user
List<SpeedDialUiItem> speedDialUiItems = new ArrayList<>();
@@ -392,4 +440,8 @@ public final class SpeedDialUiItemLoader {
}
return item.toBuilder().setChannels(newChannelsList.build()).build();
}
+
+ private SpeedDialEntryDao getSpeedDialEntryDao() {
+ return new SpeedDialEntryDatabaseHelper(appContext);
+ }
}