Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22c6b53d authored by uabdullah's avatar uabdullah Committed by android-build-merger
Browse files

Merge "Show voicemail error messages for NUI"

am: 328494b2

Change-Id: I417682ff3c8fbf5cceab6c48bafc7bfcd7b52c3d
parents 78f40f85 328494b2
Loading
Loading
Loading
Loading
+125 −39
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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. */
@@ -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.
@@ -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;
    }

@@ -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())) {
@@ -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);

@@ -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",
@@ -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);
    }
  }
}
+28 −4
Original line number Diff line number Diff line
@@ -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());
  }
}
+29 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
+90 −11
Original line number Diff line number Diff line
@@ -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>
+9 −0
Original line number Diff line number Diff line
@@ -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>