summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/voicemail
diff options
context:
space:
mode:
authoruabdullah <uabdullah@google.com>2017-12-14 09:44:33 -0800
committerCopybara-Service <copybara-piper@google.com>2017-12-14 10:46:12 -0800
commitd9eb05894f5c9d98e2d67502b01691dc54a1a2e6 (patch)
tree5e55e01841968ffaece64f5a5b0d5b8052dd15b1 /java/com/android/dialer/voicemail
parent7015dfdf76401ccd987e2a566d2edf316f1e86c5 (diff)
Support deleting voicemails
Allows voicemails to be deleted when tapping on the delete icon. Upon tapping the delete button this first deletes/hides it in the recyler view and then subsequently deletes it from the underlying table. Test: Unit test PiperOrigin-RevId: 179055594 Change-Id: I98bb7694d59b7edfcaa4ae162b194c0ef3a0292e
Diffstat (limited to 'java/com/android/dialer/voicemail')
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java87
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java1
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java35
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java6
4 files changed, 110 insertions, 19 deletions
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
index 671a39a67..a4848c8f0 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
@@ -16,23 +16,30 @@
package com.android.dialer.voicemail.listui;
import android.app.FragmentManager;
+import android.content.Context;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
+import android.net.Uri;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.android.dialer.calllogutils.CallLogDates;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
+import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.time.Clock;
import com.android.dialer.voicemail.listui.NewVoicemailViewHolder.NewVoicemailViewHolderListener;
@@ -69,6 +76,12 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
private int currentlyExpandedViewHolderId = -1;
/**
+ * It takes time to delete voicemails from the server, so we "remove" them and remember the
+ * positions we removed until a new cursor is ready.
+ */
+ Set<Integer> deletedVoicemailPosition = new ArraySet<>();
+
+ /**
* A set of (re-usable) view holders being used by the recycler view to display voicemails. This
* set may include multiple view holder with the same ID and shouldn't be used to lookup a
* specific viewholder based on this value, instead use newVoicemailViewHolderArrayMap for that
@@ -130,6 +143,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
}
public void updateCursor(Cursor updatedCursor) {
+ deletedVoicemailPosition.clear();
this.cursor = updatedCursor;
notifyDataSetChanged();
}
@@ -159,6 +173,20 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
LogUtil.enterBlock("NewVoicemailAdapter.onBindViewHolder, pos:" + position);
+ // Re-request a bind when a viewholder is deleted to ensure correct position
+ if (deletedVoicemailPosition.contains(position)) {
+ LogUtil.i(
+ "NewVoicemailAdapter.onBindViewHolder",
+ "pos:%d contains deleted voicemail, re-bind. #of deleted voicemail positions: %d",
+ position,
+ deletedVoicemailPosition.size());
+ // TODO(uabdullah): This should be removed when we support multi-select delete
+ Assert.checkArgument(
+ deletedVoicemailPosition.size() == 1, "multi-deletes not currently supported");
+ onBindViewHolder(viewHolder, ++position);
+ return;
+ }
+
// TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
printHashSet();
// TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
@@ -464,6 +492,55 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
onPreparedListener.onPrepared(mediaPlayer.getMediaPlayer());
}
+ @Override
+ public void deleteViewHolder(
+ Context context,
+ FragmentManager fragmentManager,
+ NewVoicemailViewHolder expandedViewHolder,
+ Uri voicemailUri) {
+ LogUtil.i(
+ "NewVoicemailAdapter.deleteViewHolder",
+ "deleting adapter position %d, id:%d, uri:%s ",
+ expandedViewHolder.getAdapterPosition(),
+ expandedViewHolder.getViewHolderId(),
+ String.valueOf(voicemailUri));
+
+ deletedVoicemailPosition.add(expandedViewHolder.getAdapterPosition());
+
+ Assert.checkArgument(expandedViewHolder.getViewHolderVoicemailUri().equals(voicemailUri));
+
+ notifyItemRemoved(expandedViewHolder.getAdapterPosition());
+
+ Assert.checkArgument(currentlyExpandedViewHolderId == expandedViewHolder.getViewHolderId());
+
+ collapseExpandedViewHolder(expandedViewHolder);
+
+ Worker<Pair<Context, Uri>, Integer> deleteVoicemail = this::deleteVoicemail;
+ SuccessListener<Integer> deleteVoicemailCallBack = this::onVoicemailDeleted;
+
+ DialerExecutorComponent.get(context)
+ .dialerExecutorFactory()
+ .createUiTaskBuilder(fragmentManager, "delete_voicemail", deleteVoicemail)
+ .onSuccess(deleteVoicemailCallBack)
+ .build()
+ .executeSerial(new Pair<>(context, voicemailUri));
+ }
+
+ private void onVoicemailDeleted(Integer integer) {
+ LogUtil.i("NewVoicemailAdapter.onVoicemailDeleted", "return value:%d", integer);
+ Assert.checkArgument(integer == 1, "voicemail delete was not successful");
+ }
+
+ @WorkerThread
+ private Integer deleteVoicemail(Pair<Context, Uri> contextUriPair) {
+ Assert.isWorkerThread();
+ LogUtil.enterBlock("NewVoicemailAdapter.deleteVoicemail");
+ Context context = contextUriPair.first;
+ Uri uri = contextUriPair.second;
+ LogUtil.i("NewVoicemailAdapter.deleteVoicemail", "deleting uri:%s", String.valueOf(uri));
+ return context.getContentResolver().delete(uri, null, null);
+ }
+
/**
* This function is called recursively to update the seekbar, duration, play/pause buttons of the
* expanded view holder if its playing.
@@ -731,6 +808,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
@Override
public int getItemCount() {
+ // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
LogUtil.enterBlock("NewVoicemailAdapter.getItemCount");
int numberOfHeaders = 0;
if (todayHeaderPosition != Integer.MAX_VALUE) {
@@ -739,7 +817,14 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
if (olderHeaderPosition != Integer.MAX_VALUE) {
numberOfHeaders++;
}
- return cursor.getCount() + numberOfHeaders;
+ // TODO(uabdullah): a bug Remove logging, temporarily here for debugging.
+ LogUtil.i(
+ "NewVoicemailAdapter.getItemCount",
+ "cursor cnt:%d, num of headers:%d, delete size:%d",
+ cursor.getCount(),
+ numberOfHeaders,
+ deletedVoicemailPosition.size());
+ return cursor.getCount() + numberOfHeaders - deletedVoicemailPosition.size();
}
@RowType
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
index 82e704d39..b4be42455 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java
@@ -56,6 +56,7 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba
LogUtil.i("NewVoicemailFragment.onLoadFinished", "cursor size is %d", data.getCount());
if (recyclerView.getAdapter() == null) {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+ // TODO(uabdullah): Replace getActivity().getFragmentManager() with getChildFragment()
recyclerView.setAdapter(
new NewVoicemailAdapter(
data, System::currentTimeMillis, getActivity().getFragmentManager()));
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
index 3f2de7d00..66a6fea7c 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
@@ -379,8 +379,6 @@ public final class NewVoicemailMediaPlayerView extends LinearLayout {
private void sendIntentToDownloadVoicemail(Uri uri) {
LogUtil.i("NewVoicemailMediaPlayer.sendIntentToDownloadVoicemail", "uri:%s", uri.toString());
- // Send voicemail fetch request.
- Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, uri);
Worker<Pair<Context, Uri>, Pair<String, Uri>> getVoicemailSourcePackage =
this::queryVoicemailSourcePackage;
@@ -399,7 +397,7 @@ public final class NewVoicemailMediaPlayerView extends LinearLayout {
Uri uri = booleanUriPair.second;
LogUtil.i(
"NewVoicemailMediaPlayer.sendIntent",
- "srcPkg:%s, uri:%%s",
+ "srcPkg:%s, uri:%s",
sourcePackage,
String.valueOf(uri));
Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, uri);
@@ -465,23 +463,11 @@ public final class NewVoicemailMediaPlayerView extends LinearLayout {
"NewVoicemailMediaPlayer.phoneButtonListener",
"speaker request for voicemailUri: %s",
voicemailUri.toString());
- }
- };
-
- private final View.OnClickListener deleteButtonListener =
- new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- LogUtil.i(
- "NewVoicemailMediaPlayer.deleteButtonListener",
- "delete voicemailUri %s",
- voicemailUri.toString());
- // TODO(uabdullah): This will be removed in cl/177404259. It only sets the has_content to
- // 0, to allow the annotated call log to change, and refresh the fragment. This is used to
- // demo and test the downloading of voicemails from the server.
ContentValues contentValues = new ContentValues();
contentValues.put("has_content", 0);
-
+ // TODO(uabdullah): It only sets the has_content to 0, to allow the annotated call log to
+ // change, and refresh the fragment. This is used to demo and test the downloading of
+ // voicemails from the server. This will be removed once we implement this listener.
try {
getContext().getContentResolver().update(voicemailUri, contentValues, "type = 4", null);
} catch (Exception e) {
@@ -494,6 +480,19 @@ public final class NewVoicemailMediaPlayerView extends LinearLayout {
}
};
+ private final View.OnClickListener deleteButtonListener =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.deleteButtonListener",
+ "delete voicemailUri %s",
+ String.valueOf(voicemailUri));
+ newVoicemailViewHolderListener.deleteViewHolder(
+ getContext(), fragmentManager, newVoicemailViewHolder, voicemailUri);
+ }
+ };
+
/**
* This is only called to update the media player view of the seekbar, and the duration and the
* play button. For constant updates the adapter should seek track. This is the state when a
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
index 072546552..bc23288bb 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
@@ -363,6 +363,12 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
void pauseViewHolder(NewVoicemailViewHolder expandedViewHolder);
void resumePausedViewHolder(NewVoicemailViewHolder expandedViewHolder);
+
+ void deleteViewHolder(
+ Context context,
+ FragmentManager fragmentManager,
+ NewVoicemailViewHolder expandedViewHolder,
+ Uri uri);
}
@Override