Loading java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java +125 −39 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.media.MediaPlayer.OnPreparedListener; import android.net.Uri; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; Loading @@ -43,9 +44,15 @@ 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; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessageCreator; import com.android.dialer.voicemail.listui.error.VoicemailStatus; import com.android.dialer.voicemail.model.VoicemailEntry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; Loading @@ -66,6 +73,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> } private Cursor cursor; private Cursor voicemailStatusCursor; private final Clock clock; /** {@link Integer#MAX_VALUE} when the "Today" header should not be displayed. */ Loading @@ -81,6 +89,8 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> /** A valid id for {@link VoicemailEntry} is greater than 0 */ private int currentlyExpandedViewHolderId = -1; private VoicemailErrorMessage voicemailErrorMessage; /** * 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. Loading Loading @@ -248,34 +258,14 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> if (viewHolder instanceof NewVoicemailHeaderViewHolder) { LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a header", position); NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); if (position == todayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_today); } else if (position == yesterdayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday); } else if (position == olderHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_older); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } onBindHeaderViewHolder(viewHolder, position); return; } if (viewHolder instanceof NewVoicemailAlertViewHolder) { LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a alert", position); NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); Assert.checkArgument(position == 0); if (position == voicemailAlertPosition) { // TODO(a bug): Update this with the alert messages alertViewHolder.setHeader("Temporary placeholder, update this with the alert messages"); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } onBindAlertViewHolder(viewHolder, position); return; } Loading @@ -285,26 +275,13 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> position); NewVoicemailViewHolder newVoicemailViewHolder = (NewVoicemailViewHolder) viewHolder; int previousHeaders = 0; if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) { previousHeaders++; } if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) { previousHeaders++; } if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) { previousHeaders++; } if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) { previousHeaders++; } int nonVoicemailEntryHeaders = getHeaderCountAtPosition(position); LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d, prevHeaderCount:%d", "view holder at pos:%d, nonVoicemailEntryHeaders:%d", position, previousHeaders); nonVoicemailEntryHeaders); // Remove if the viewholder is being recycled. if (newVoicemailViewHolderArrayMap.containsKey(newVoicemailViewHolder.getViewHolderId())) { Loading @@ -322,7 +299,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> } newVoicemailViewHolder.reset(); cursor.moveToPosition(position - previousHeaders); cursor.moveToPosition(position - nonVoicemailEntryHeaders); newVoicemailViewHolder.bindViewHolderValuesFromAdapter( cursor, fragmentManager, mediaPlayer, position, currentlyExpandedViewHolderId); Loading Loading @@ -378,6 +355,72 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> printArrayMap(); } private int getHeaderCountAtPosition(int position) { int previousHeaders = 0; if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) { previousHeaders++; } if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) { previousHeaders++; } if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) { previousHeaders++; } if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) { previousHeaders++; } return previousHeaders; } private void onBindAlertViewHolder(ViewHolder viewHolder, int position) { LogUtil.i( "NewVoicemailAdapter.onBindAlertViewHolder", "pos:%d, voicemailAlertPosition:%d", position, voicemailAlertPosition); NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); Assert.checkArgument(position == 0, "position is not 0"); Assert.checkArgument( position == voicemailAlertPosition, String.format( Locale.US, "position:%d and voicemailAlertPosition:%d are different", position, voicemailAlertPosition)); Assert.checkArgument(viewType == RowType.VOICEMAIL_ALERT, "Invalid row type: " + viewType); Assert.checkArgument( voicemailErrorMessage.getActions().size() <= 2, "Too many actions: " + voicemailErrorMessage.getActions().size()); alertViewHolder.setTitle(voicemailErrorMessage.getTitle()); alertViewHolder.setDescription(voicemailErrorMessage.getDescription()); if (!voicemailErrorMessage.getActions().isEmpty()) { alertViewHolder.setPrimaryButton(voicemailErrorMessage.getActions().get(0)); } if (voicemailErrorMessage.getActions().size() > 1) { alertViewHolder.setSecondaryButton(voicemailErrorMessage.getActions().get(1)); } } private void onBindHeaderViewHolder(ViewHolder viewHolder, int position) { NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); if (position == todayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_today); } else if (position == yesterdayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday); } else if (position == olderHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_older); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } } private void printArrayMap() { LogUtil.i( "NewVoicemailAdapter.printArrayMap", Loading Loading @@ -958,4 +1001,47 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> LogUtil.i("NewVoicemailAdapter.checkAndPlayVoicemail", "not playing downloaded voicemail"); } } @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public void setVoicemailStatusCursor(Cursor voicemailStatusCursor) { this.voicemailStatusCursor = voicemailStatusCursor; } // TODO(uabdullah): Handle ToS properly public void updateAlert(Context context) { if (voicemailStatusCursor == null) { LogUtil.i("NewVoicemailAdapter.updateAlert", "status cursor was null"); return; } LogUtil.i( "NewVoicemailAdapter.updateAlert", "status cursor size was " + voicemailStatusCursor.getCount()); List<VoicemailStatus> statuses = new ArrayList<>(); while (voicemailStatusCursor.moveToNext()) { VoicemailStatus status = new VoicemailStatus(context, voicemailStatusCursor); if (status.isActive()) { statuses.add(status); // TODO(uabdullah): addServiceStateListener } } voicemailErrorMessage = null; VoicemailErrorMessageCreator messageCreator = new VoicemailErrorMessageCreator(); for (VoicemailStatus status : statuses) { voicemailErrorMessage = messageCreator.create(context, status, null); if (voicemailErrorMessage != null) { break; } } if (voicemailErrorMessage != null) { voicemailAlertPosition = 0; updateHeaderPositions(); notifyItemChanged(0); } } } java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java +28 −4 Original line number Diff line number Diff line Loading @@ -18,19 +18,43 @@ package com.android.dialer.voicemail.listui; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage.Action; /** ViewHolder for {@link NewVoicemailAdapter} to display voicemail error states. */ final class NewVoicemailAlertViewHolder extends ViewHolder { private final TextView errorTextView; private final TextView voicemailErrorTitleTextView; private final TextView voicemailErrorDetailsTextView; private final Button primaryButton; private final Button secondaryButton; NewVoicemailAlertViewHolder(View view) { super(view); errorTextView = view.findViewById(R.id.new_voicemail_alert_text); voicemailErrorTitleTextView = view.findViewById(R.id.voicemail_alert_header); voicemailErrorDetailsTextView = view.findViewById(R.id.voicemail_alert_details); primaryButton = view.findViewById(R.id.voicemail_alert_primary_button); secondaryButton = view.findViewById(R.id.voicemail_alert_primary_button); } void setHeader(String error) { errorTextView.setText(error); void setTitle(CharSequence error) { voicemailErrorTitleTextView.setText(error); } void setDescription(CharSequence error) { voicemailErrorDetailsTextView.setText(error); } void setPrimaryButton(Action action) { primaryButton.setVisibility(View.VISIBLE); primaryButton.setText(action.getText()); primaryButton.setOnClickListener(action.getListener()); } void setSecondaryButton(Action action) { secondaryButton.setVisibility(View.VISIBLE); secondaryButton.setText(action.getText()); secondaryButton.setOnClickListener(action.getListener()); } } java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java +29 −0 Original line number Diff line number Diff line Loading @@ -28,11 +28,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.database.CallLogQueryHandler.Listener; // TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart /** Fragment for Dialer Voicemail Tab. */ public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> { private RecyclerView recyclerView; private CallLogQueryHandler callLogQueryHandler; @Nullable @Override Loading Loading @@ -72,6 +76,31 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba ((NewVoicemailAdapter) recyclerView.getAdapter()).updateCursor(data); ((NewVoicemailAdapter) recyclerView.getAdapter()).checkAndPlayVoicemail(); } callLogQueryHandler = new CallLogQueryHandler( getContext(), getContext().getContentResolver(), new NewVoicemailFragmentListener()); callLogQueryHandler.fetchVoicemailStatus(); } private final class NewVoicemailFragmentListener implements Listener { @Override public void onVoicemailStatusFetched(Cursor statusCursor) { LogUtil.enterBlock("NewVoicemailFragmentListener.onVoicemailStatusFetched"); ((NewVoicemailAdapter) recyclerView.getAdapter()).setVoicemailStatusCursor(statusCursor); ((NewVoicemailAdapter) recyclerView.getAdapter()).updateAlert(getContext()); } @Override public void onVoicemailUnreadCountFetched(Cursor cursor) {} @Override public void onMissedCallsUnreadCountFetched(Cursor cursor) {} @Override public boolean onCallsFetched(Cursor combinedCursor) { return false; } } @Override Loading java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml +90 −11 Original line number Diff line number Diff line Loading @@ -14,17 +14,96 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> <RelativeLayout <!-- TODO(uabdullah): Use a relative layout instead of nested linear layouts.--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:id="@+id/voicemail_alert_content" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- TODO(uabdullah): Confirm with UX on mocks --> android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/alert_main_padding" android:paddingBottom="@dimen/alert_main_padding" android:paddingStart="@dimen/alert_main_padding" android:paddingEnd="@dimen/alert_main_padding" android:gravity="top" android:orientation="horizontal"> <ImageView android:id="@+id/voicemail_alert_icon" android:layout_width="@dimen/voicemail_promo_card_icon_size" android:layout_height="@dimen/voicemail_promo_card_icon_size" android:layout_gravity="top" android:src="@drawable/ic_voicemail_error_24px"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/voicemail_promo_card_main_padding" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/voicemail_alert_header" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/voicemail_promo_card_title_padding" android:layout_gravity="center_vertical" android:singleLine="false" android:text="Voicemail Alert" android:textSize="@dimen/voicemail_promo_card_title_text_size"/> <TextView android:id="@+id/new_voicemail_alert_text" style="@style/SecondaryText" android:id="@+id/voicemail_alert_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:lineSpacingExtra="@dimen/voicemail_promo_card_line_spacing" android:singleLine="false" android:text="This is a voicemail alert message." android:textSize="@dimen/voicemail_promo_card_message_size"/> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/voicemail_alert_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="end" android:paddingTop="10dp" android:paddingBottom="10dp" android:paddingStart="16dp" android:paddingEnd="16dp" android:gravity="end" android:minHeight="56dp" android:orientation="horizontal"> <Button android:id="@+id/voicemail_alert_secondary_button" style="@style/TosButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/dialer_theme_color"/> <Button android:id="@+id/voicemail_alert_primary_button" style="@style/TosButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/voicemail_header_margin_start" android:layout_centerVertical="true"/> </RelativeLayout> android:textColor="@color/dialer_theme_color"/> </LinearLayout> <LinearLayout android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center" android:divider="?android:dividerHorizontal" android:gravity="center" android:orientation="vertical" android:showDividers="middle"> </LinearLayout> </LinearLayout> java/com/android/dialer/voicemail/listui/res/values/dimens.xml +9 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,13 @@ <dimen name="voicemail_tos_image_size">280dp</dimen> <!-- Dimensions for voicemail alert --> <dimen name="alert_main_padding">24dp</dimen> <dimen name="voicemail_promo_card_icon_size">24dp</dimen> <dimen name="voicemail_promo_card_main_padding">24dp</dimen> <dimen name="voicemail_promo_card_title_padding">12dp</dimen> <dimen name="voicemail_promo_card_title_text_size">16sp</dimen> <dimen name="voicemail_promo_card_line_spacing">4dp</dimen> <dimen name="voicemail_promo_card_message_size">14sp</dimen> </resources> Loading
java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java +125 −39 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.media.MediaPlayer.OnPreparedListener; import android.net.Uri; import android.support.annotation.IntDef; import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; Loading @@ -43,9 +44,15 @@ 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; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessageCreator; import com.android.dialer.voicemail.listui.error.VoicemailStatus; import com.android.dialer.voicemail.model.VoicemailEntry; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; Loading @@ -66,6 +73,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> } private Cursor cursor; private Cursor voicemailStatusCursor; private final Clock clock; /** {@link Integer#MAX_VALUE} when the "Today" header should not be displayed. */ Loading @@ -81,6 +89,8 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> /** A valid id for {@link VoicemailEntry} is greater than 0 */ private int currentlyExpandedViewHolderId = -1; private VoicemailErrorMessage voicemailErrorMessage; /** * 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. Loading Loading @@ -248,34 +258,14 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> if (viewHolder instanceof NewVoicemailHeaderViewHolder) { LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a header", position); NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); if (position == todayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_today); } else if (position == yesterdayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday); } else if (position == olderHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_older); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } onBindHeaderViewHolder(viewHolder, position); return; } if (viewHolder instanceof NewVoicemailAlertViewHolder) { LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d is a alert", position); NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); Assert.checkArgument(position == 0); if (position == voicemailAlertPosition) { // TODO(a bug): Update this with the alert messages alertViewHolder.setHeader("Temporary placeholder, update this with the alert messages"); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } onBindAlertViewHolder(viewHolder, position); return; } Loading @@ -285,26 +275,13 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> position); NewVoicemailViewHolder newVoicemailViewHolder = (NewVoicemailViewHolder) viewHolder; int previousHeaders = 0; if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) { previousHeaders++; } if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) { previousHeaders++; } if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) { previousHeaders++; } if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) { previousHeaders++; } int nonVoicemailEntryHeaders = getHeaderCountAtPosition(position); LogUtil.i( "NewVoicemailAdapter.onBindViewHolder", "view holder at pos:%d, prevHeaderCount:%d", "view holder at pos:%d, nonVoicemailEntryHeaders:%d", position, previousHeaders); nonVoicemailEntryHeaders); // Remove if the viewholder is being recycled. if (newVoicemailViewHolderArrayMap.containsKey(newVoicemailViewHolder.getViewHolderId())) { Loading @@ -322,7 +299,7 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> } newVoicemailViewHolder.reset(); cursor.moveToPosition(position - previousHeaders); cursor.moveToPosition(position - nonVoicemailEntryHeaders); newVoicemailViewHolder.bindViewHolderValuesFromAdapter( cursor, fragmentManager, mediaPlayer, position, currentlyExpandedViewHolderId); Loading Loading @@ -378,6 +355,72 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> printArrayMap(); } private int getHeaderCountAtPosition(int position) { int previousHeaders = 0; if (voicemailAlertPosition != Integer.MAX_VALUE && position > voicemailAlertPosition) { previousHeaders++; } if (todayHeaderPosition != Integer.MAX_VALUE && position > todayHeaderPosition) { previousHeaders++; } if (yesterdayHeaderPosition != Integer.MAX_VALUE && position > yesterdayHeaderPosition) { previousHeaders++; } if (olderHeaderPosition != Integer.MAX_VALUE && position > olderHeaderPosition) { previousHeaders++; } return previousHeaders; } private void onBindAlertViewHolder(ViewHolder viewHolder, int position) { LogUtil.i( "NewVoicemailAdapter.onBindAlertViewHolder", "pos:%d, voicemailAlertPosition:%d", position, voicemailAlertPosition); NewVoicemailAlertViewHolder alertViewHolder = (NewVoicemailAlertViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); Assert.checkArgument(position == 0, "position is not 0"); Assert.checkArgument( position == voicemailAlertPosition, String.format( Locale.US, "position:%d and voicemailAlertPosition:%d are different", position, voicemailAlertPosition)); Assert.checkArgument(viewType == RowType.VOICEMAIL_ALERT, "Invalid row type: " + viewType); Assert.checkArgument( voicemailErrorMessage.getActions().size() <= 2, "Too many actions: " + voicemailErrorMessage.getActions().size()); alertViewHolder.setTitle(voicemailErrorMessage.getTitle()); alertViewHolder.setDescription(voicemailErrorMessage.getDescription()); if (!voicemailErrorMessage.getActions().isEmpty()) { alertViewHolder.setPrimaryButton(voicemailErrorMessage.getActions().get(0)); } if (voicemailErrorMessage.getActions().size() > 1) { alertViewHolder.setSecondaryButton(voicemailErrorMessage.getActions().get(1)); } } private void onBindHeaderViewHolder(ViewHolder viewHolder, int position) { NewVoicemailHeaderViewHolder headerViewHolder = (NewVoicemailHeaderViewHolder) viewHolder; @RowType int viewType = getItemViewType(position); if (position == todayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_today); } else if (position == yesterdayHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_yesterday); } else if (position == olderHeaderPosition) { headerViewHolder.setHeader(R.string.new_voicemail_header_older); } else { throw Assert.createIllegalStateFailException( "Unexpected view type " + viewType + " at position: " + position); } } private void printArrayMap() { LogUtil.i( "NewVoicemailAdapter.printArrayMap", Loading Loading @@ -958,4 +1001,47 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder> LogUtil.i("NewVoicemailAdapter.checkAndPlayVoicemail", "not playing downloaded voicemail"); } } @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public void setVoicemailStatusCursor(Cursor voicemailStatusCursor) { this.voicemailStatusCursor = voicemailStatusCursor; } // TODO(uabdullah): Handle ToS properly public void updateAlert(Context context) { if (voicemailStatusCursor == null) { LogUtil.i("NewVoicemailAdapter.updateAlert", "status cursor was null"); return; } LogUtil.i( "NewVoicemailAdapter.updateAlert", "status cursor size was " + voicemailStatusCursor.getCount()); List<VoicemailStatus> statuses = new ArrayList<>(); while (voicemailStatusCursor.moveToNext()) { VoicemailStatus status = new VoicemailStatus(context, voicemailStatusCursor); if (status.isActive()) { statuses.add(status); // TODO(uabdullah): addServiceStateListener } } voicemailErrorMessage = null; VoicemailErrorMessageCreator messageCreator = new VoicemailErrorMessageCreator(); for (VoicemailStatus status : statuses) { voicemailErrorMessage = messageCreator.create(context, status, null); if (voicemailErrorMessage != null) { break; } } if (voicemailErrorMessage != null) { voicemailAlertPosition = 0; updateHeaderPositions(); notifyItemChanged(0); } } }
java/com/android/dialer/voicemail/listui/NewVoicemailAlertViewHolder.java +28 −4 Original line number Diff line number Diff line Loading @@ -18,19 +18,43 @@ package com.android.dialer.voicemail.listui; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.android.dialer.voicemail.listui.error.VoicemailErrorMessage.Action; /** ViewHolder for {@link NewVoicemailAdapter} to display voicemail error states. */ final class NewVoicemailAlertViewHolder extends ViewHolder { private final TextView errorTextView; private final TextView voicemailErrorTitleTextView; private final TextView voicemailErrorDetailsTextView; private final Button primaryButton; private final Button secondaryButton; NewVoicemailAlertViewHolder(View view) { super(view); errorTextView = view.findViewById(R.id.new_voicemail_alert_text); voicemailErrorTitleTextView = view.findViewById(R.id.voicemail_alert_header); voicemailErrorDetailsTextView = view.findViewById(R.id.voicemail_alert_details); primaryButton = view.findViewById(R.id.voicemail_alert_primary_button); secondaryButton = view.findViewById(R.id.voicemail_alert_primary_button); } void setHeader(String error) { errorTextView.setText(error); void setTitle(CharSequence error) { voicemailErrorTitleTextView.setText(error); } void setDescription(CharSequence error) { voicemailErrorDetailsTextView.setText(error); } void setPrimaryButton(Action action) { primaryButton.setVisibility(View.VISIBLE); primaryButton.setText(action.getText()); primaryButton.setOnClickListener(action.getListener()); } void setSecondaryButton(Action action) { secondaryButton.setVisibility(View.VISIBLE); secondaryButton.setText(action.getText()); secondaryButton.setOnClickListener(action.getListener()); } }
java/com/android/dialer/voicemail/listui/NewVoicemailFragment.java +29 −0 Original line number Diff line number Diff line Loading @@ -28,11 +28,15 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.android.dialer.common.LogUtil; import com.android.dialer.database.CallLogQueryHandler; import com.android.dialer.database.CallLogQueryHandler.Listener; // TODO(uabdullah): Register content observer for VoicemailContract.Status.CONTENT_URI in onStart /** Fragment for Dialer Voicemail Tab. */ public final class NewVoicemailFragment extends Fragment implements LoaderCallbacks<Cursor> { private RecyclerView recyclerView; private CallLogQueryHandler callLogQueryHandler; @Nullable @Override Loading Loading @@ -72,6 +76,31 @@ public final class NewVoicemailFragment extends Fragment implements LoaderCallba ((NewVoicemailAdapter) recyclerView.getAdapter()).updateCursor(data); ((NewVoicemailAdapter) recyclerView.getAdapter()).checkAndPlayVoicemail(); } callLogQueryHandler = new CallLogQueryHandler( getContext(), getContext().getContentResolver(), new NewVoicemailFragmentListener()); callLogQueryHandler.fetchVoicemailStatus(); } private final class NewVoicemailFragmentListener implements Listener { @Override public void onVoicemailStatusFetched(Cursor statusCursor) { LogUtil.enterBlock("NewVoicemailFragmentListener.onVoicemailStatusFetched"); ((NewVoicemailAdapter) recyclerView.getAdapter()).setVoicemailStatusCursor(statusCursor); ((NewVoicemailAdapter) recyclerView.getAdapter()).updateAlert(getContext()); } @Override public void onVoicemailUnreadCountFetched(Cursor cursor) {} @Override public void onMissedCallsUnreadCountFetched(Cursor cursor) {} @Override public boolean onCallsFetched(Cursor combinedCursor) { return false; } } @Override Loading
java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_entry_alert.xml +90 −11 Original line number Diff line number Diff line Loading @@ -14,17 +14,96 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> <RelativeLayout <!-- TODO(uabdullah): Use a relative layout instead of nested linear layouts.--> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:id="@+id/voicemail_alert_content" android:layout_width="match_parent" android:layout_height="wrap_content"> <!-- TODO(uabdullah): Confirm with UX on mocks --> android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="@dimen/alert_main_padding" android:paddingBottom="@dimen/alert_main_padding" android:paddingStart="@dimen/alert_main_padding" android:paddingEnd="@dimen/alert_main_padding" android:gravity="top" android:orientation="horizontal"> <ImageView android:id="@+id/voicemail_alert_icon" android:layout_width="@dimen/voicemail_promo_card_icon_size" android:layout_height="@dimen/voicemail_promo_card_icon_size" android:layout_gravity="top" android:src="@drawable/ic_voicemail_error_24px"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/voicemail_promo_card_main_padding" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/voicemail_alert_header" android:textStyle="bold" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/voicemail_promo_card_title_padding" android:layout_gravity="center_vertical" android:singleLine="false" android:text="Voicemail Alert" android:textSize="@dimen/voicemail_promo_card_title_text_size"/> <TextView android:id="@+id/new_voicemail_alert_text" style="@style/SecondaryText" android:id="@+id/voicemail_alert_details" android:layout_width="wrap_content" android:layout_height="wrap_content" android:lineSpacingExtra="@dimen/voicemail_promo_card_line_spacing" android:singleLine="false" android:text="This is a voicemail alert message." android:textSize="@dimen/voicemail_promo_card_message_size"/> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/voicemail_alert_button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="end" android:paddingTop="10dp" android:paddingBottom="10dp" android:paddingStart="16dp" android:paddingEnd="16dp" android:gravity="end" android:minHeight="56dp" android:orientation="horizontal"> <Button android:id="@+id/voicemail_alert_secondary_button" style="@style/TosButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/dialer_theme_color"/> <Button android:id="@+id/voicemail_alert_primary_button" style="@style/TosButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="@dimen/voicemail_header_margin_start" android:layout_centerVertical="true"/> </RelativeLayout> android:textColor="@color/dialer_theme_color"/> </LinearLayout> <LinearLayout android:layout_width="0dip" android:layout_height="match_parent" android:layout_weight="1" android:layout_gravity="center" android:divider="?android:dividerHorizontal" android:gravity="center" android:orientation="vertical" android:showDividers="middle"> </LinearLayout> </LinearLayout>
java/com/android/dialer/voicemail/listui/res/values/dimens.xml +9 −0 Original line number Diff line number Diff line Loading @@ -41,4 +41,13 @@ <dimen name="voicemail_tos_image_size">280dp</dimen> <!-- Dimensions for voicemail alert --> <dimen name="alert_main_padding">24dp</dimen> <dimen name="voicemail_promo_card_icon_size">24dp</dimen> <dimen name="voicemail_promo_card_main_padding">24dp</dimen> <dimen name="voicemail_promo_card_title_padding">12dp</dimen> <dimen name="voicemail_promo_card_title_text_size">16sp</dimen> <dimen name="voicemail_promo_card_line_spacing">4dp</dimen> <dimen name="voicemail_promo_card_message_size">14sp</dimen> </resources>