From c1fb21775fbaa33785d4e9abb46d34dce7e7b5f3 Mon Sep 17 00:00:00 2001 From: mdooley Date: Tue, 6 Feb 2018 14:55:10 -0800 Subject: Adding voicemail donation promo This cl shows a voicemail donation promo the first time a user tries to rate a transcription. It also changes the good/bad rating links to thumbs up/down icons. The 'learn more' link still needs the real URL. screen shots: https://drive.google.com/open?id=0B9o_KvtLkcuIOERUNUJId3FVY3UzUS0wVUdQQVpCS1lmM3Nz https://drive.google.com/open?id=0B9o_KvtLkcuIWkNVMDV1VTJ4VUMtakVwSE1UTGdUWjljTUV3 https://drive.google.com/open?id=0B9o_KvtLkcuIeU1ndG1palRkTnNJQWVYLXgyMnd4TjBDOFI4 mocks: https://drive.google.com/file/d/1FIhXDkn3h3xI7liVdJEraq47MoKQM3hi/view https://drive.google.com/file/d/1uTm58QCvFOBycsGP21vgvEGTq_Imgkqi/view Bug: 37340510 Test: manual tests PiperOrigin-RevId: 184745497 Change-Id: I40fd1e211311c3127f215ede2e44b22f345dcf8b --- .../drawable/quantum_ic_thumb_down_grey600_24.xml | 29 +++ .../drawable/quantum_ic_thumb_up_grey600_24.xml | 29 +++ .../dialer/app/calllog/PhoneCallDetailsHelper.java | 196 ++++++++++++++++++--- .../dialer/app/res/layout/call_log_list_item.xml | 27 +-- java/com/android/dialer/app/res/values/colors.xml | 3 + java/com/android/dialer/app/res/values/strings.xml | 57 +++--- java/com/android/dialer/app/res/values/styles.xml | 19 +- .../com/android/dialer/theme/res/values/dimens.xml | 2 +- 8 files changed, 283 insertions(+), 79 deletions(-) create mode 100644 assets/quantum/res/drawable/quantum_ic_thumb_down_grey600_24.xml create mode 100644 assets/quantum/res/drawable/quantum_ic_thumb_up_grey600_24.xml diff --git a/assets/quantum/res/drawable/quantum_ic_thumb_down_grey600_24.xml b/assets/quantum/res/drawable/quantum_ic_thumb_down_grey600_24.xml new file mode 100644 index 000000000..fec2563e4 --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_thumb_down_grey600_24.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/assets/quantum/res/drawable/quantum_ic_thumb_up_grey600_24.xml b/assets/quantum/res/drawable/quantum_ic_thumb_up_grey600_24.xml new file mode 100644 index 000000000..06a4cbd3e --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_thumb_up_grey600_24.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java index e23d92c2e..82c98156b 100644 --- a/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java +++ b/java/com/android/dialer/app/calllog/PhoneCallDetailsHelper.java @@ -16,7 +16,9 @@ package com.android.dialer.app.calllog; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; import android.content.res.Resources; import android.graphics.Typeface; import android.net.Uri; @@ -25,11 +27,18 @@ import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.v4.content.ContextCompat; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; import android.text.format.DateUtils; +import android.text.method.LinkMovementMethod; +import android.text.style.TextAppearanceSpan; +import android.text.style.URLSpan; import android.text.util.Linkify; +import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.android.dialer.app.R; @@ -41,7 +50,9 @@ import com.android.dialer.compat.telephony.TelephonyManagerCompat; import com.android.dialer.logging.ContactSource; import com.android.dialer.oem.MotorolaUtils; import com.android.dialer.phonenumberutil.PhoneNumberHelper; +import com.android.dialer.storage.StorageComponent; import com.android.dialer.util.DialerUtils; +import com.android.voicemail.VoicemailClient; import com.android.voicemail.VoicemailComponent; import com.android.voicemail.impl.transcribe.TranscriptionRatingHelper; import com.google.internal.communications.voicemailtranscription.v1.TranscriptionRatingValue; @@ -56,6 +67,9 @@ public class PhoneCallDetailsHelper /** The maximum number of icons will be shown to represent the call types in a group. */ private static final int MAX_CALL_TYPE_ICONS = 3; + private static final String PREF_VOICEMAIL_DONATION_PROMO_SHOWN_KEY = + "pref_voicemail_donation_promo_shown_key"; + private final Context context; private final Resources resources; private final CallLogCache callLogCache; @@ -165,15 +179,10 @@ public class PhoneCallDetailsHelper String transcript = ""; String branding = ""; - boolean showRatingPrompt = false; if (!TextUtils.isEmpty(details.transcription)) { transcript = details.transcription; - // Show a transcription quality rating prompt or set the branding text if the voicemail was - // transcribed by google - if (shouldShowTranscriptionRating(details.transcriptionState, details.accountHandle)) { - showRatingPrompt = true; - } else if (details.transcriptionState == VoicemailCompat.TRANSCRIPTION_AVAILABLE + if (details.transcriptionState == VoicemailCompat.TRANSCRIPTION_AVAILABLE || details.transcriptionState == VoicemailCompat.TRANSCRIPTION_AVAILABLE_AND_RATED) { branding = resources.getString(R.string.voicemail_transcription_branding_text); } @@ -198,28 +207,25 @@ public class PhoneCallDetailsHelper } views.voicemailTranscriptionView.setText(transcript); - if (showRatingPrompt) { - views.voicemailTranscriptionBrandingView.setVisibility(View.GONE); - views.voicemailTranscriptionBrandingView.setText(branding); + views.voicemailTranscriptionBrandingView.setText(branding); - View ratingView = views.voicemailTranscriptionRatingView; + View ratingView = views.voicemailTranscriptionRatingView; + if (shouldShowTranscriptionRating(details.transcriptionState, details.accountHandle)) { ratingView.setVisibility(View.VISIBLE); ratingView .findViewById(R.id.voicemail_transcription_rating_good) .setOnClickListener( view -> recordTranscriptionRating( - TranscriptionRatingValue.GOOD_TRANSCRIPTION, details)); + TranscriptionRatingValue.GOOD_TRANSCRIPTION, details, ratingView)); ratingView .findViewById(R.id.voicemail_transcription_rating_bad) .setOnClickListener( view -> - recordTranscriptionRating(TranscriptionRatingValue.BAD_TRANSCRIPTION, details)); + recordTranscriptionRating( + TranscriptionRatingValue.BAD_TRANSCRIPTION, details, ratingView)); } else { - views.voicemailTranscriptionRatingView.setVisibility(View.GONE); - - views.voicemailTranscriptionBrandingView.setVisibility(View.VISIBLE); - views.voicemailTranscriptionBrandingView.setText(branding); + ratingView.setVisibility(View.GONE); } } @@ -237,22 +243,156 @@ public class PhoneCallDetailsHelper private boolean shouldShowTranscriptionRating( int transcriptionState, PhoneAccountHandle account) { - // TODO(mdooley): add a configurable random element here? - return transcriptionState == VoicemailCompat.TRANSCRIPTION_AVAILABLE - && VoicemailComponent.get(context) - .getVoicemailClient() - .isVoicemailDonationEnabled(context, account); + if (transcriptionState != VoicemailCompat.TRANSCRIPTION_AVAILABLE) { + return false; + } + + VoicemailClient client = VoicemailComponent.get(context).getVoicemailClient(); + if (client.isVoicemailDonationEnabled(context, account)) { + return true; + } + + // Also show the rating option if voicemail transcription is available (but not enabled) + // and the donation promo has not yet been shown. + if (client.isVoicemailDonationAvailable(context) && !hasSeenVoicemailDonationPromo(context)) { + return true; + } + + return false; } private void recordTranscriptionRating( - TranscriptionRatingValue ratingValue, PhoneCallDetails details) { + TranscriptionRatingValue ratingValue, PhoneCallDetails details, View ratingView) { LogUtil.enterBlock("PhoneCallDetailsHelper.recordTranscriptionRating"); - TranscriptionRatingHelper.sendRating( - context, - ratingValue, - Uri.parse(details.voicemailUri), - this::onRatingSuccess, - this::onRatingFailure); + + if (shouldShowVoicemailDonationPromo(context)) { + showVoicemailDonationPromo(ratingValue, details, ratingView); + } else { + TranscriptionRatingHelper.sendRating( + context, + ratingValue, + Uri.parse(details.voicemailUri), + this::onRatingSuccess, + this::onRatingFailure); + } + } + + static boolean shouldShowVoicemailDonationPromo(Context context) { + VoicemailClient client = VoicemailComponent.get(context).getVoicemailClient(); + return client.isVoicemailTranscriptionAvailable(context) + && client.isVoicemailDonationAvailable(context) + && !hasSeenVoicemailDonationPromo(context); + } + + static boolean hasSeenVoicemailDonationPromo(Context context) { + return StorageComponent.get(context.getApplicationContext()) + .unencryptedSharedPrefs() + .getBoolean(PREF_VOICEMAIL_DONATION_PROMO_SHOWN_KEY, false); + } + + private void showVoicemailDonationPromo( + TranscriptionRatingValue ratingValue, PhoneCallDetails details, View ratingView) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setMessage(getVoicemailDonationPromoContent()); + builder.setPositiveButton( + R.string.voicemail_donation_promo_opt_in, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int button) { + LogUtil.i("PhoneCallDetailsHelper.showVoicemailDonationPromo", "onClick"); + dialog.cancel(); + recordPromoShown(context); + VoicemailComponent.get(context) + .getVoicemailClient() + .setVoicemailDonationEnabled(context, details.accountHandle, true); + TranscriptionRatingHelper.sendRating( + context, + ratingValue, + Uri.parse(details.voicemailUri), + PhoneCallDetailsHelper.this::onRatingSuccess, + PhoneCallDetailsHelper.this::onRatingFailure); + ratingView.setVisibility(View.GONE); + } + }); + builder.setNegativeButton( + R.string.voicemail_donation_promo_opt_out, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int button) { + dialog.cancel(); + recordPromoShown(context); + ratingView.setVisibility(View.GONE); + } + }); + builder.setCancelable(true); + AlertDialog dialog = builder.create(); + + // Use a custom title to prevent truncation, sigh + TextView title = new TextView(context); + title.setText( + ratingValue == TranscriptionRatingValue.GOOD_TRANSCRIPTION + ? R.string.voicemail_donation_promo_good_title + : R.string.voicemail_donation_promo_bad_title); + title.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL)); + title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); + title.setTextColor(ContextCompat.getColor(context, R.color.dialer_primary_text_color)); + title.setPadding( + dpsToPixels(context, 24), /* left */ + dpsToPixels(context, 10), /* top */ + dpsToPixels(context, 24), /* right */ + dpsToPixels(context, 0)); /* bottom */ + dialog.setCustomTitle(title); + + dialog.show(); + + // Make the message link clickable and adjust the appearance of the message and buttons + TextView textView = (TextView) dialog.findViewById(android.R.id.message); + textView.setLineSpacing(0, 1.2f); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (positiveButton != null) { + positiveButton.setTextColor( + context + .getResources() + .getColor(R.color.voicemail_donation_promo_positive_button_text_color)); + } + Button negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE); + if (negativeButton != null) { + negativeButton.setTextColor( + context + .getResources() + .getColor(R.color.voicemail_donation_promo_negative_button_text_color)); + } + } + + private static int dpsToPixels(Context context, int dps) { + return (int) + (TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, dps, context.getResources().getDisplayMetrics())); + } + + private static void recordPromoShown(Context context) { + StorageComponent.get(context.getApplicationContext()) + .unencryptedSharedPrefs() + .edit() + .putBoolean(PREF_VOICEMAIL_DONATION_PROMO_SHOWN_KEY, true) + .apply(); + } + + private SpannableString getVoicemailDonationPromoContent() { + CharSequence content = context.getString(R.string.voicemail_donation_promo_content); + CharSequence learnMore = context.getString(R.string.voicemail_donation_promo_learn_more); + String learnMoreUrl = context.getString(R.string.voicemail_donation_promo_learn_more_url); + SpannableString span = new SpannableString(content + "\n" + learnMore); + int end = span.length(); + int start = end - learnMore.length(); + span.setSpan(new URLSpan(learnMoreUrl), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + span.setSpan( + new TextAppearanceSpan(context, R.style.PromoLinkStyle), + start, + end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return span; } @Override diff --git a/java/com/android/dialer/app/res/layout/call_log_list_item.xml b/java/com/android/dialer/app/res/layout/call_log_list_item.xml index a24552ba4..1b776b42c 100644 --- a/java/com/android/dialer/app/res/layout/call_log_list_item.xml +++ b/java/com/android/dialer/app/res/layout/call_log_list_item.xml @@ -193,36 +193,27 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" - android:gravity="start" + android:gravity="start|center_vertical" android:focusable="true" android:text="@string/voicemail_transcription_rating"/> - - - + android:src="@drawable/quantum_ic_thumb_up_grey600_24"/> - + android:src="@drawable/quantum_ic_thumb_down_grey600_24"/> diff --git a/java/com/android/dialer/app/res/values/colors.xml b/java/com/android/dialer/app/res/values/colors.xml index 84a381f21..e79c5c5ed 100644 --- a/java/com/android/dialer/app/res/values/colors.xml +++ b/java/com/android/dialer/app/res/values/colors.xml @@ -80,4 +80,7 @@ #E0E0E0 #bdbdbd + #FF2A56C6 + #FF757575 + diff --git a/java/com/android/dialer/app/res/values/strings.xml b/java/com/android/dialer/app/res/values/strings.xml index d4f3f8180..2d5542bbf 100644 --- a/java/com/android/dialer/app/res/values/strings.xml +++ b/java/com/android/dialer/app/res/values/strings.xml @@ -675,33 +675,38 @@ [CHAR LIMIT=64] --> Transcript not available. No speech detected. - - Rate transcription quality + + Thanks! Would you like to help us improve transcriptions? + + + Sorry. Would you like to help us improve transcriptions? + + + + Let Google review your voicemail messages to improve transcription quality. Your + voicemail messages will not be tied to your Google Account. + - - Good - - - Bad - - - or + + Learn more + + + https:www.google.com + + + Yes, I\'m in + + + No thanks + + + Rate transcription quality Thanks for your feedback diff --git a/java/com/android/dialer/app/res/values/styles.xml b/java/com/android/dialer/app/res/values/styles.xml index b275cecd1..869f1276d 100644 --- a/java/com/android/dialer/app/res/values/styles.xml +++ b/java/com/android/dialer/app/res/values/styles.xml @@ -258,15 +258,22 @@ - + + + diff --git a/java/com/android/dialer/theme/res/values/dimens.xml b/java/com/android/dialer/theme/res/values/dimens.xml index 88b8a0423..e7c947782 100644 --- a/java/com/android/dialer/theme/res/values/dimens.xml +++ b/java/com/android/dialer/theme/res/values/dimens.xml @@ -22,7 +22,7 @@ 16sp 12sp 14sp - 14sp + 16sp 48dp 15dp -- cgit v1.2.3 From 4b9f28f9f3cc5b580ddb021ebeeb824ca97080ba Mon Sep 17 00:00:00 2001 From: yueg Date: Tue, 6 Feb 2018 17:32:47 -0800 Subject: Bubble layout change. - Flip back-to-call button icon. - Use different button height for portrait and landscape. In order to make it work, we also create new ViewHolder object when bubble shows and remove reset() when bubble hides. Bug: 67605985 Test: NewBubbleImplIntegrationTest, NewBubbleImplTest, NewReturnToCallControllerTest PiperOrigin-RevId: 184768224 Change-Id: If4e613b12e39c647c34f4cb63a7f934043d42ec7 --- .../quantum_ic_exit_to_app_flip_vd_theme_24.xml | 29 ++++++++++++++++++++++ .../quantum_ic_exit_to_app_vd_theme_24.xml | 25 ------------------- .../incallui/NewReturnToCallController.java | 13 +++------- java/com/android/newbubble/NewBubble.java | 3 --- java/com/android/newbubble/stub/NewBubbleStub.java | 3 --- 5 files changed, 32 insertions(+), 41 deletions(-) create mode 100644 assets/quantum/res/drawable/quantum_ic_exit_to_app_flip_vd_theme_24.xml delete mode 100644 assets/quantum/res/drawable/quantum_ic_exit_to_app_vd_theme_24.xml diff --git a/assets/quantum/res/drawable/quantum_ic_exit_to_app_flip_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_exit_to_app_flip_vd_theme_24.xml new file mode 100644 index 000000000..3dfbf2b0e --- /dev/null +++ b/assets/quantum/res/drawable/quantum_ic_exit_to_app_flip_vd_theme_24.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/assets/quantum/res/drawable/quantum_ic_exit_to_app_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_exit_to_app_vd_theme_24.xml deleted file mode 100644 index 5279f0483..000000000 --- a/assets/quantum/res/drawable/quantum_ic_exit_to_app_vd_theme_24.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - \ No newline at end of file diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java index e37b14734..c588dc4e1 100644 --- a/java/com/android/incallui/NewReturnToCallController.java +++ b/java/com/android/incallui/NewReturnToCallController.java @@ -119,14 +119,6 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au } } - private void hideAndReset() { - if (bubble != null) { - bubble.hideAndReset(); - } else { - LogUtil.i("ReturnToCallController.reset", "reset() called without calling show()"); - } - } - private void show() { if (bubble == null) { bubble = startBubble(); @@ -189,7 +181,7 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au if (!TelecomUtil.isInCall(context) || CallList.getInstance().getIncomingCall() != null) { bubble.showText(context.getText(R.string.incall_call_ended)); } - hideAndReset(); + hide(); } else { startContactInfoSearch(); } @@ -258,7 +250,8 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au // Return to call actions.add( Action.builder() - .setIconDrawable(context.getDrawable(R.drawable.quantum_ic_exit_to_app_vd_theme_24)) + .setIconDrawable( + context.getDrawable(R.drawable.quantum_ic_exit_to_app_flip_vd_theme_24)) .setIntent(fullScreen) .setName(context.getText(R.string.bubble_return_to_call)) .setCheckable(false) diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java index 8f1be6458..785593c5c 100644 --- a/java/com/android/newbubble/NewBubble.java +++ b/java/com/android/newbubble/NewBubble.java @@ -37,9 +37,6 @@ public interface NewBubble { /** Hide the bubble. */ void hide(); - /** Hide the bubble and reset to initial state */ - void hideAndReset(); - /** Returns whether the bubble is currently visible */ boolean isVisible(); diff --git a/java/com/android/newbubble/stub/NewBubbleStub.java b/java/com/android/newbubble/stub/NewBubbleStub.java index 4079aaaba..f5121cff9 100644 --- a/java/com/android/newbubble/stub/NewBubbleStub.java +++ b/java/com/android/newbubble/stub/NewBubbleStub.java @@ -35,9 +35,6 @@ public class NewBubbleStub implements NewBubble { @Override public void hide() {} - @Override - public void hideAndReset() {} - @Override public boolean isVisible() { return false; -- cgit v1.2.3