diff options
Diffstat (limited to 'java/com/android/dialer/speeddial')
6 files changed, 96 insertions, 33 deletions
diff --git a/java/com/android/dialer/speeddial/SpeedDialAdapter.java b/java/com/android/dialer/speeddial/SpeedDialAdapter.java index 6f6ac5498..8a37e97dd 100644 --- a/java/com/android/dialer/speeddial/SpeedDialAdapter.java +++ b/java/com/android/dialer/speeddial/SpeedDialAdapter.java @@ -210,4 +210,9 @@ public final class SpeedDialAdapter extends RecyclerView.Adapter<RecyclerView.Vi public void setItemTouchHelper(ItemTouchHelper itemTouchHelper) { this.itemTouchHelper = itemTouchHelper; } + + /** Returns true if there are suggested contacts. */ + public boolean hasFrequents() { + return !speedDialUiItems.isEmpty() && getItemViewType(getItemCount() - 1) == RowType.SUGGESTION; + } } diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index 26893a8d3..b74c06239 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -34,6 +34,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; +import com.android.dialer.common.FragmentUtils; import com.android.dialer.common.LogUtil; import com.android.dialer.common.concurrent.DialerExecutorComponent; import com.android.dialer.common.concurrent.SupportUiListener; @@ -132,11 +133,6 @@ public class SpeedDialFragment extends Fragment { return rootLayout; } - public boolean hasFrequents() { - // TODO(calderwoodra) - return false; - } - @Override public void onResume() { super.onResume(); @@ -173,12 +169,17 @@ public class SpeedDialFragment extends Fragment { } private void onSpeedDialUiItemListLoaded(ImmutableList<SpeedDialUiItem> speedDialUiItems) { + LogUtil.enterBlock("SpeedDialFragment.onSpeedDialUiItemListLoaded"); // TODO(calderwoodra): Use DiffUtil to properly update and animate the change adapter.setSpeedDialUiItems( UiItemLoaderComponent.get(getContext()) .speedDialUiItemLoader() .insertDuoChannels(getContext(), speedDialUiItems)); adapter.notifyDataSetChanged(); + if (getActivity() != null) { + FragmentUtils.getParentUnsafe(this, HostInterface.class) + .setHasFrequents(adapter.hasFrequents()); + } } @Override @@ -359,4 +360,10 @@ public class SpeedDialFragment extends Fragment { Contacts.CONTENT_URI, String.valueOf(speedDialUiItem.contactId())))); } } + + /** Interface for {@link SpeedDialFragment} to communicate with its host/parent. */ + public interface HostInterface { + + void setHasFrequents(boolean hasFrequents); + } } diff --git a/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java b/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java index ce771c3c8..4d6ac2d7f 100644 --- a/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java +++ b/java/com/android/dialer/speeddial/database/SpeedDialEntryDao.java @@ -17,6 +17,7 @@ package com.android.dialer.speeddial.database; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; /** * Interface that databases support speed dial entries should implement. @@ -32,8 +33,10 @@ public interface SpeedDialEntryDao { * Insert new entries. * * <p>{@link SpeedDialEntry#id() ids} must be null. + * + * @return a map of the inserted entries to their new ids. */ - void insert(ImmutableList<SpeedDialEntry> entries); + ImmutableMap<SpeedDialEntry, Long> insert(ImmutableList<SpeedDialEntry> entries); /** * Insert a new entry. @@ -59,11 +62,12 @@ public interface SpeedDialEntryDao { /** * Inserts, updates and deletes rows all in on transaction. * + * @return a map of the inserted entries to their new ids. * @see #insert(ImmutableList) * @see #update(ImmutableList) * @see #delete(ImmutableList) */ - void insertUpdateAndDelete( + ImmutableMap<SpeedDialEntry, Long> insertUpdateAndDelete( ImmutableList<SpeedDialEntry> entriesToInsert, ImmutableList<SpeedDialEntry> entriesToUpdate, ImmutableList<Long> entriesToDelete); diff --git a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java index 137933fbe..544bb3613 100644 --- a/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java +++ b/java/com/android/dialer/speeddial/database/SpeedDialEntryDatabaseHelper.java @@ -26,6 +26,7 @@ import com.android.dialer.common.Assert; import com.android.dialer.common.database.Selection; import com.android.dialer.speeddial.database.SpeedDialEntry.Channel; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.List; @@ -132,30 +133,39 @@ public final class SpeedDialEntryDatabaseHelper extends SQLiteOpenHelper } @Override - public void insert(ImmutableList<SpeedDialEntry> entries) { + public ImmutableMap<SpeedDialEntry, Long> insert(ImmutableList<SpeedDialEntry> entries) { if (entries.isEmpty()) { - return; + return ImmutableMap.of(); } SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { - insert(db, entries); + ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = insert(db, entries); db.setTransactionSuccessful(); + return insertedEntriesToIdsMap; } finally { db.endTransaction(); db.close(); } } - private void insert(SQLiteDatabase writeableDatabase, ImmutableList<SpeedDialEntry> entries) { + private ImmutableMap<SpeedDialEntry, Long> insert( + SQLiteDatabase writeableDatabase, ImmutableList<SpeedDialEntry> entries) { + ImmutableMap.Builder<SpeedDialEntry, Long> insertedEntriesToIdsMap = ImmutableMap.builder(); for (SpeedDialEntry entry : entries) { Assert.checkArgument(entry.id() == null); - if (writeableDatabase.insert(TABLE_NAME, null, buildContentValuesWithoutId(entry)) == -1L) { + long id = writeableDatabase.insert(TABLE_NAME, null, buildContentValuesWithoutId(entry)); + if (id == -1L) { throw Assert.createUnsupportedOperationFailException( "Attempted to insert a row that already exists."); } + // It's impossible to insert two identical entries but this is an important assumption we need + // to verify because there's an assumption that each entry will correspond to exactly one id. + // ImmutableMap#put verifies this check for us. + insertedEntriesToIdsMap.put(entry, id); } + return insertedEntriesToIdsMap.build(); } @Override @@ -255,20 +265,21 @@ public final class SpeedDialEntryDatabaseHelper extends SQLiteOpenHelper } @Override - public void insertUpdateAndDelete( + public ImmutableMap<SpeedDialEntry, Long> insertUpdateAndDelete( ImmutableList<SpeedDialEntry> entriesToInsert, ImmutableList<SpeedDialEntry> entriesToUpdate, ImmutableList<Long> entriesToDelete) { if (entriesToInsert.isEmpty() && entriesToUpdate.isEmpty() && entriesToDelete.isEmpty()) { - return; + return ImmutableMap.of(); } SQLiteDatabase db = getWritableDatabase(); db.beginTransaction(); try { - insert(db, entriesToInsert); + ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = insert(db, entriesToInsert); update(db, entriesToUpdate); delete(db, entriesToDelete); db.setTransactionSuccessful(); + return insertedEntriesToIdsMap; } finally { db.endTransaction(); db.close(); diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java index 24bc776e7..9bda3fb31 100644 --- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java +++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItem.java @@ -136,6 +136,15 @@ public abstract class SpeedDialUiItem { return builder.build(); } + public SpeedDialEntry buildSpeedDialEntry() { + return SpeedDialEntry.builder() + .setId(speedDialEntryId()) + .setLookupKey(lookupKey()) + .setContactId(contactId()) + .setDefaultChannel(defaultChannel()) + .build(); + } + /** * Returns a video channel if there is exactly one video channel or the default channel is a video * channel. diff --git a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java index 7107706fe..921468773 100644 --- a/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java +++ b/java/com/android/dialer/speeddial/loader/SpeedDialUiItemLoader.java @@ -44,6 +44,7 @@ import com.android.dialer.speeddial.database.SpeedDialEntry.Channel; import com.android.dialer.speeddial.database.SpeedDialEntryDao; import com.android.dialer.speeddial.database.SpeedDialEntryDatabaseHelper; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import java.util.ArrayList; @@ -146,13 +147,7 @@ public final class SpeedDialUiItemLoader { } // Insert a new entry into the SpeedDialEntry database - getSpeedDialEntryDao() - .insert( - SpeedDialEntry.builder() - .setLookupKey(item.lookupKey()) - .setContactId(item.contactId()) - .setDefaultChannel(item.defaultChannel()) - .build()); + getSpeedDialEntryDao().insert(item.buildSpeedDialEntry()); } return loadSpeedDialUiItemsInternal(); } @@ -216,23 +211,55 @@ public final class SpeedDialUiItemLoader { contact.toBuilder().setDefaultChannel(contact.channels().get(0)).build()); } else if (speedDialUiItems.stream().noneMatch(c -> c.contactId() == contact.contactId())) { - entriesToInsert.add( - SpeedDialEntry.builder() - .setLookupKey(contact.lookupKey()) - .setContactId(contact.contactId()) - .setDefaultChannel(contact.defaultChannel()) - .build()); + entriesToInsert.add(contact.buildSpeedDialEntry()); // These are our newly starred contacts speedDialUiItems.add(contact); } } - db.insertUpdateAndDelete( - ImmutableList.copyOf(entriesToInsert), - ImmutableList.copyOf(entriesToUpdate), - ImmutableList.copyOf(entriesToDelete)); - return ImmutableList.copyOf(speedDialUiItems); + ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap = + db.insertUpdateAndDelete( + ImmutableList.copyOf(entriesToInsert), + ImmutableList.copyOf(entriesToUpdate), + ImmutableList.copyOf(entriesToDelete)); + return speedDialUiItemsWithUpdatedIds(speedDialUiItems, insertedEntriesToIdsMap); + } + + /** + * Since newly starred contacts sometimes aren't in the SpeedDialEntry database, we couldn't set + * their ids when we created our initial list of {@link SpeedDialUiItem speedDialUiItems}. Now + * that we've inserted the entries into the database and we have their ids, build a new list of + * speedDialUiItems with the now known ids. + */ + private ImmutableList<SpeedDialUiItem> speedDialUiItemsWithUpdatedIds( + List<SpeedDialUiItem> speedDialUiItems, + ImmutableMap<SpeedDialEntry, Long> insertedEntriesToIdsMap) { + if (insertedEntriesToIdsMap.isEmpty()) { + // There were no newly inserted entries, so all entries ids are set already. + return ImmutableList.copyOf(speedDialUiItems); + } + + ImmutableList.Builder<SpeedDialUiItem> updatedItems = ImmutableList.builder(); + for (SpeedDialUiItem speedDialUiItem : speedDialUiItems) { + SpeedDialEntry entry = speedDialUiItem.buildSpeedDialEntry(); + if (insertedEntriesToIdsMap.containsKey(entry)) { + // Get the id for newly inserted entry, update our SpeedDialUiItem and add it to our list + Long id = Assert.isNotNull(insertedEntriesToIdsMap.get(entry)); + updatedItems.add(speedDialUiItem.toBuilder().setSpeedDialEntryId(id).build()); + continue; + } + + // Starred contacts that aren't in the map, should already have speed dial entry ids. + // Non-starred contacts (suggestions) aren't in the speed dial entry database, so they + // shouldn't have speed dial entry ids. + Assert.checkArgument( + speedDialUiItem.isStarred() == (speedDialUiItem.speedDialEntryId() != null), + "Contact must be starred with a speed dial entry id, or not starred with no id " + + "(suggested contacts)"); + updatedItems.add(speedDialUiItem); + } + return updatedItems.build(); } /** |