diff options
Diffstat (limited to 'java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java')
-rw-r--r-- | java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java | 258 |
1 files changed, 236 insertions, 22 deletions
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java index f08e6bfd7..02b05db03 100644 --- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java +++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java @@ -15,17 +15,22 @@ */ package com.android.dialer.voicemail.listui; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + import android.app.FragmentManager; import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.support.annotation.VisibleForTesting; +import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.QuickContactBadge; import android.widget.TextView; +import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog; +import com.android.dialer.common.Assert; import com.android.dialer.common.LogUtil; import com.android.dialer.contactphoto.ContactPhotoManager; import com.android.dialer.lettertile.LetterTileDrawable; @@ -44,6 +49,8 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On private final Clock clock; private boolean isViewHolderExpanded; private int viewHolderId; + private VoicemailEntry voicemailEntryOfViewHolder; + @NonNull private Uri viewHolderVoicemailUri; private final NewVoicemailViewHolderListener voicemailViewHolderListener; NewVoicemailViewHolder( @@ -58,19 +65,45 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On mediaPlayerView = view.findViewById(R.id.new_voicemail_media_player); this.clock = clock; voicemailViewHolderListener = newVoicemailViewHolderListener; + + viewHolderId = -1; + isViewHolderExpanded = false; + viewHolderVoicemailUri = null; } - void bind(Cursor cursor, FragmentManager fragmentManager) { - VoicemailEntry voicemailEntry = VoicemailCursorLoader.toVoicemailEntry(cursor); - viewHolderId = voicemailEntry.id(); - primaryTextView.setText(VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntry)); + /** + * When the {@link RecyclerView} displays voicemail entries, it might recycle the views upon + * scrolling. In that case we need to ensure that the member variables of this {@link + * NewVoicemailViewHolder} and its views are correctly set, especially when this {@link + * NewVoicemailViewHolder} is recycled. + * + * @param cursor the voicemail data from {@link AnnotatedCallLog} generated by the {@link + * VoicemailCursorLoader} related + * @param fragmentManager FragmentManager retrieved from {@link + * NewVoicemailFragment#getActivity()} + * @param mediaPlayer + * @param position the position of the item within the adapter's data set. + * @param currentlyExpandedViewHolderId the value the adapter keeps track of which viewholder if + */ + void bindViewHolderValuesFromAdapter( + Cursor cursor, + FragmentManager fragmentManager, + NewVoicemailMediaPlayer mediaPlayer, + int position, + int currentlyExpandedViewHolderId) { + + voicemailEntryOfViewHolder = VoicemailCursorLoader.toVoicemailEntry(cursor); + viewHolderId = voicemailEntryOfViewHolder.id(); + viewHolderVoicemailUri = Uri.parse(voicemailEntryOfViewHolder.voicemailUri()); + primaryTextView.setText( + VoicemailEntryText.buildPrimaryVoicemailText(context, voicemailEntryOfViewHolder)); secondaryTextView.setText( - VoicemailEntryText.buildSecondaryVoicemailText(context, clock, voicemailEntry)); + VoicemailEntryText.buildSecondaryVoicemailText(context, clock, voicemailEntryOfViewHolder)); - String voicemailTranscription = voicemailEntry.transcription(); + String voicemailTranscription = voicemailEntryOfViewHolder.transcription(); if (TextUtils.isEmpty(voicemailTranscription)) { - transcriptionTextView.setVisibility(View.GONE); + transcriptionTextView.setVisibility(GONE); transcriptionTextView.setText(null); } else { transcriptionTextView.setVisibility(View.VISIBLE); @@ -78,9 +111,49 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On } itemView.setOnClickListener(this); - setPhoto(voicemailEntry); - mediaPlayerView.setVoicemailEntryValues(voicemailEntry); - mediaPlayerView.setFragmentManager(fragmentManager); + setPhoto(voicemailEntryOfViewHolder); + + // Update the expanded/collapsed state of this view holder + // Only update the binding of the mediaPlayerView of the expanded view holder + if (viewHolderId == currentlyExpandedViewHolderId) { + LogUtil.i( + "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter", + "viewHolderId:%d is expanded, update its mediaplayer view", + viewHolderId); + expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues( + voicemailEntryOfViewHolder, fragmentManager, mediaPlayer, voicemailViewHolderListener); + LogUtil.i( + "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter", + "After 2nd updating the MPPlayerView: viewHolderId:%d, uri:%s, MediaplayerView(after " + + "updated):%s, adapter position passed down:%d, getAdapterPos:%d", + viewHolderId, + String.valueOf(viewHolderVoicemailUri), + String.valueOf(mediaPlayerView.getVoicemailUri()), + position, + getAdapterPosition()); + Assert.checkArgument( + mediaPlayerView.getVisibility() == VISIBLE, + "a expanded viewholder should have its media player view visible"); + } else { + LogUtil.i( + "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter", + "viewHolderId:%d is not the expanded one, collapse it and don't update the MpView", + viewHolderId); + collapseViewHolder(); + Assert.checkArgument( + mediaPlayerView.getVisibility() == GONE, + "a collapsed viewholder should not have its media player view visible"); + } + LogUtil.i( + "NewVoicemailViewHolder.bindViewHolderValuesFromAdapter", + "Final value after updating: viewHolderId:%d, uri:%s, MediaplayerView(not updated):%s," + + " adapter position passed down:%d, getAdapterPos:%d, MPPlayerVisibility:%b", + viewHolderId, + String.valueOf(viewHolderVoicemailUri), + String.valueOf(mediaPlayerView.getVoicemailUri()), + position, + getAdapterPosition(), + mediaPlayerView.getVisibility() == VISIBLE); } // TODO(uabdullah): Consider/Implement TYPE (e.g Spam, TYPE_VOICEMAIL) @@ -96,19 +169,148 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On } void collapseViewHolder() { + LogUtil.i( + "NewVoicemailViewHolder.collapseViewHolder", + "viewHolderId:%d is being collapsed, its MPViewUri:%s, its Uri is :%s", + viewHolderId, + String.valueOf(mediaPlayerView.getVoicemailUri()), + String.valueOf(viewHolderVoicemailUri)); transcriptionTextView.setMaxLines(1); isViewHolderExpanded = false; - mediaPlayerView.setVisibility(View.GONE); + mediaPlayerView.setVisibility(GONE); + } + + // When we are recycling the views ensure that we reset the viewHolder, as if its brand new + public void reset() { + LogUtil.i( + "NewVoicemailViewHolder.reset()", + "Reset the viewholder, currently viewHolderId:%d, uri:%s, isViewHolderExpanded:%b, " + + "its MediaPlayerViewUri:%s", + viewHolderId, + String.valueOf(viewHolderVoicemailUri), + isViewHolderExpanded, + String.valueOf(mediaPlayerView.getVoicemailUri())); + + viewHolderId = -1; + isViewHolderExpanded = false; + viewHolderVoicemailUri = null; + + mediaPlayerView.reset(); + + LogUtil.i( + "NewVoicemailViewHolder.reset()", + "Reset the viewholder, after resetting viewHolderId:%d, uri:%s, isViewHolderExpanded:%b", + viewHolderId, + String.valueOf(viewHolderVoicemailUri), + isViewHolderExpanded); } - void expandViewHolder() { - LogUtil.i("NewVoicemailViewHolder.expandViewHolder", "voicemail id: %d", viewHolderId); + /** + * Is only called when a user either clicks a {@link NewVoicemailViewHolder} to expand it or if + * the user had already expanded, then scrolled the {@link NewVoicemailViewHolder} out of view and + * then scrolled it back into view, and during the binding (as the views are recyled in {@link + * RecyclerView}) we restore the expanded state of the {@link NewVoicemailViewHolder}. + * + * <p>This function also tracks if the state of this viewholder is expanded. + * + * @param voicemailEntry are the voicemail related values from the {@link AnnotatedCallLog} + * @param fragmentManager FragmentManager retrieved from {@link + * NewVoicemailFragment#getActivity()} + * @param mediaPlayer there should only be one instance of this passed down from the {@link + * NewVoicemailAdapter} + * @param voicemailViewHolderListener + */ + void expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues( + VoicemailEntry voicemailEntry, + FragmentManager fragmentManager, + NewVoicemailMediaPlayer mediaPlayer, + NewVoicemailViewHolderListener voicemailViewHolderListener) { + + Assert.isNotNull(voicemailViewHolderListener); + Assert.checkArgument( + voicemailEntry.id() == viewHolderId, "ensure that the adapter binding has taken place"); + Assert.checkArgument( + Uri.parse(voicemailEntry.voicemailUri()).equals(viewHolderVoicemailUri), + "ensure that the adapter binding has taken place"); + LogUtil.i( + "NewVoicemailViewHolder.expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues", + "voicemail id: %d, value of isViewHolderExpanded:%b, before setting it to be true, and" + + " value of ViewholderUri:%s, MPView:%s, before updating it", + viewHolderId, + isViewHolderExpanded, + String.valueOf(viewHolderVoicemailUri), + String.valueOf(mediaPlayerView.getVoicemailUri())); + transcriptionTextView.setMaxLines(999); isViewHolderExpanded = true; + // Once the media player is visible update its state mediaPlayerView.setVisibility(View.VISIBLE); + mediaPlayerView.bindValuesFromAdapterOfExpandedViewHolderMediaPlayerView( + this, voicemailEntry, fragmentManager, mediaPlayer, voicemailViewHolderListener); + LogUtil.i( + "NewVoicemailViewHolder.expandAndBindViewHolderAndMediaPlayerViewWithAdapterValues", + "voicemail id: %d, value of isViewHolderExpanded:%b, after setting it to be true, and" + + " value of ViewholderUri:%s, MPView:%s, after updating it", + viewHolderId, + isViewHolderExpanded, + String.valueOf(viewHolderVoicemailUri), + String.valueOf(mediaPlayerView.getVoicemailUri())); + } + + /** + * Called when we want to update the voicemail that is currently playing Updates the Seekbar, + * duration timer and the play/pause button visibility when the expanded voicemail is being + * played. + */ + public void updateMediaPlayerViewWithPlayingState( + NewVoicemailViewHolder newVoicemailViewHolder, NewVoicemailMediaPlayer mp) { + + LogUtil.i( + "NewVoicemailViewHolder.updateMediaPlayerViewWithPlayingState", + "viewholderUri:%s, mediaPlayerViewUri:%s, MPPosition:%d, MpDuration:%d, MpIsPlaying:%b", + newVoicemailViewHolder.getViewHolderVoicemailUri().toString(), + mediaPlayerView.getVoicemailUri().toString(), + mp.getCurrentPosition(), + mp.getDuration(), + mp.isPlaying()); + + Assert.checkArgument( + mp.isPlaying(), + "this method is only called when we are certain that the media player is playing"); + + LogUtil.i( + "NewVoicemailViewHolder.updateMediaPlayerViewWithPlayingState", + "viewholderUri:%s, mediaPlayerViewUri:%s", + newVoicemailViewHolder.getViewHolderVoicemailUri().toString(), + mediaPlayerView.getVoicemailUri().toString()); + Assert.checkArgument( + newVoicemailViewHolder + .getViewHolderVoicemailUri() + .equals(mediaPlayerView.getVoicemailUri()), + "the mediaplayer view must be that of the viewholder we are updating"); + Assert.checkArgument( + mp.getLastPlayedOrPlayingVoicemailUri() + .equals(mp.getLastPreparedOrPreparingToPlayVoicemailUri()), + "the media player view we are attempting to update should be of the " + + "currently prepared and playing voicemail"); + + mediaPlayerView.updateSeekBarDurationAndShowPlayButton(mp); + } + + public void setMediaPlayerViewToResetState( + NewVoicemailViewHolder currentlyExpandedViewHolderOnScreen, + NewVoicemailMediaPlayer mediaPlayer) { + Assert.isNotNull(currentlyExpandedViewHolderOnScreen); + mediaPlayerView.setToResetState(currentlyExpandedViewHolderOnScreen, mediaPlayer); + } + + public void setPausedStateOfMediaPlayerView(Uri uri, NewVoicemailMediaPlayer mediaPlayer) { + Assert.checkArgument(viewHolderVoicemailUri.equals(uri)); + Assert.checkArgument(mediaPlayerView.getVoicemailUri().equals(uri)); + Assert.checkArgument(mediaPlayerView.getVoicemailUri().equals(viewHolderVoicemailUri)); + mediaPlayerView.setToPausedState(uri, mediaPlayer); } - @VisibleForTesting(otherwise = VisibleForTesting.NONE) boolean isViewHolderExpanded() { return isViewHolderExpanded; } @@ -117,25 +319,37 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On return viewHolderId; } + public Uri getViewHolderVoicemailUri() { + return viewHolderVoicemailUri; + } + interface NewVoicemailViewHolderListener { - void onViewHolderExpanded(NewVoicemailViewHolder expandedViewHolder); + void expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders( + NewVoicemailViewHolder expandedViewHolder, + VoicemailEntry voicemailEntryOfViewHolder, + NewVoicemailViewHolderListener listener); + + void collapseExpandedViewHolder(NewVoicemailViewHolder expandedViewHolder); - void onViewHolderCollapsed(NewVoicemailViewHolder expandedViewHolder); + void pauseViewHolder(NewVoicemailViewHolder expandedViewHolder); + + void resumePausedViewHolder(NewVoicemailViewHolder expandedViewHolder); } @Override public void onClick(View v) { LogUtil.i( "NewVoicemailViewHolder.onClick", - "voicemail id: %d, isViewHolderExpanded:%b", + "voicemail id: %d, isViewHolderCurrentlyExpanded:%b", viewHolderId, isViewHolderExpanded); if (isViewHolderExpanded) { - collapseViewHolder(); - voicemailViewHolderListener.onViewHolderCollapsed(this); + voicemailViewHolderListener.collapseExpandedViewHolder(this); } else { - expandViewHolder(); - voicemailViewHolderListener.onViewHolderExpanded(this); + voicemailViewHolderListener.expandViewHolderFirstTimeAndCollapseAllOtherVisibleViewHolders( + this, + Assert.isNotNull(voicemailEntryOfViewHolder), + Assert.isNotNull(voicemailViewHolderListener)); } } } |