diff options
8 files changed, 283 insertions, 79 deletions
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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="vector" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:name="path" + android:pathData="M 15 3 L 6 3 C 5.17 3 4.46 3.5 4.16 4.22 L 1.14 11.27 C 1.05 11.5 1 11.74 1 12 L 1 13.91 L 1.01 13.92 L 1 14 C 1 15.1 1.9 16 3 16 L 9.31 16 L 8.36 20.57 L 8.33 20.89 C 8.33 21.3 8.5 21.68 8.77 21.95 L 9.83 23 L 16.42 16.41 C 16.78 16.05 17 15.55 17 15 L 17 5 C 17 3.9 16.1 3 15 3 Z M 19 3 L 19 15 L 23 15 L 23 3 L 19 3 Z" + android:fillColor="#757575" + android:strokeWidth="1"/> +</vector> 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + android:name="vector" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:name="path" + android:pathData="M 1 21 L 5 21 L 5 9 L 1 9 L 1 21 Z M 23 10 C 23 8.9 22.1 8 21 8 L 14.69 8 L 15.64 3.43 L 15.67 3.11 C 15.67 2.7 15.5 2.32 15.23 2.05 L 14.17 1 L 7.59 7.59 C 7.22 7.95 7 8.45 7 9 L 7 19 C 7 20.1 7.9 21 9 21 L 18 21 C 18.83 21 19.54 20.5 19.84 19.78 L 22.86 12.73 C 22.95 12.5 23 12.26 23 12 L 23 10.09 L 22.99 10.08 L 23 10 Z" + android:fillColor="#757575" + android:strokeWidth="1"/> +</vector> 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"/> - <TextView - style="@style/TranscriptionQualityRatingLink" + <ImageView + style="@style/TranscriptionQualityRatingIcon" android:id="@+id/voicemail_transcription_rating_good" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="end" - android:focusable="true" - android:text="@string/voicemail_transcription_rating_good"/> - - <TextView - style="@style/TranscriptionQualityRating" - android:id="@+id/voicemail_transcription_rating_separator" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="end" + android:gravity="end|center_vertical" android:focusable="true" - android:text="@string/voicemail_transcription_rating_separator"/> + android:src="@drawable/quantum_ic_thumb_up_grey600_24"/> - <TextView - style="@style/TranscriptionQualityRatingLink" + <ImageView + style="@style/TranscriptionQualityRatingIcon" android:id="@+id/voicemail_transcription_rating_bad" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="end" + android:gravity="end|center_vertical" android:focusable="true" - android:text="@string/voicemail_transcription_rating_bad"/> + android:src="@drawable/quantum_ic_thumb_down_grey600_24"/> </LinearLayout> 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 @@ <color name="blocked_number_disabled_emergency_background_color">#E0E0E0</color> <color name="add_blocked_number_icon_color">#bdbdbd</color> + <color name="voicemail_donation_promo_positive_button_text_color">#FF2A56C6</color> + <color name="voicemail_donation_promo_negative_button_text_color">#FF757575</color> + </resources> 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] --> <string name="voicemail_transcription_failed_no_speech">Transcript not available. No speech detected.</string> - <!-- Prompt asking the user to rate the quality of the voicemail transcription [CHAR LIMIT=30] - voicemail_transcription_rating, voicemail_transcription_rating_good, - voicemail_transcription_rating_separator and voicemail_transcription_rating_bad are - used together to form the rating prompt: 'Rate transcription quality Good or Bad' - where 'Good' and 'Bad' are clickable links. --> - <string name="voicemail_transcription_rating">Rate transcription quality</string> + <!-- Title of voicemail donation promo dialog, show after clicking a 'thumbs up' rating icon + [CHAR LIMIT=64] --> + <string name="voicemail_donation_promo_good_title">Thanks! Would you like to help us improve transcriptions?</string> + + <!-- Title of voicemail donation promo dialog, show after clicking a 'thumbs up' rating icon + [CHAR LIMIT=64] --> + <string name="voicemail_donation_promo_bad_title">Sorry. Would you like to help us improve transcriptions?</string> + + <!-- Content of voicemail donation promo dialog + [CHAR LIMIT=NONE] --> + <string name="voicemail_donation_promo_content"> + Let Google review your voicemail messages to improve transcription quality. Your + voicemail messages will not be tied to your Google Account. + </string> - <!-- Rating choice indicating that the voicemail transcription was good [CHAR LIMIT=10] - voicemail_transcription_rating, voicemail_transcription_rating_good, - voicemail_transcription_rating_separator and voicemail_transcription_rating_bad are - used together to form the rating prompt: 'Rate transcription quality Good or Bad' - where 'Good' and 'Bad' are clickable links. --> - <string name="voicemail_transcription_rating_good">Good</string> - - <!-- Rating choice indicating that the voicemail transcription was bad [CHAR LIMIT=10] - voicemail_transcription_rating, voicemail_transcription_rating_good, - voicemail_transcription_rating_separator and voicemail_transcription_rating_bad are - used together to form the rating prompt: 'Rate transcription quality Good or Bad' - where 'Good' and 'Bad' are clickable links. --> - <string name="voicemail_transcription_rating_bad">Bad</string> - - <!-- Separator between the good and bad transcription rating choices [CHAR LIMIT=10] - voicemail_transcription_rating, voicemail_transcription_rating_good, - voicemail_transcription_rating_separator and voicemail_transcription_rating_bad are - used together to form the rating prompt: 'Rate transcription quality Good or Bad' - where 'Good' and 'Bad' are clickable links. --> - <string name="voicemail_transcription_rating_separator"> or </string> + <!-- Text for a 'learn more' link at the end of the voicemail donation promo dialog content --> + <string name="voicemail_donation_promo_learn_more">Learn more</string> + + <!-- TODO(mdooley): get real url --> + <string translatable="false" name="voicemail_donation_promo_learn_more_url">https:www.google.com</string> + + <!-- Label for the voicemail donation promo dialog opt-in button + [CHAR LIMIT=20] --> + <string name="voicemail_donation_promo_opt_in">Yes, I\'m in</string> + + <!-- Label for the voicemail donation promo dialog opt-out button + [CHAR LIMIT=20] --> + <string name="voicemail_donation_promo_opt_out">No thanks</string> + + <!-- Prompt asking the user to rate the quality of the voicemail transcription + [CHAR LIMIT=30] --> + <string name="voicemail_transcription_rating">Rate transcription quality</string> <!-- Message displayed after user has rated a voicemail transcription [CHAR LIMIT=30] --> <string name="voicemail_transcription_rating_thanks">Thanks for your feedback</string> 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 @@ <style name="TranscriptionQualityRating"> <item name="android:textColor">@color/call_log_voicemail_transcript_branding_color</item> <item name="android:textSize">@dimen/call_log_voicemail_transcription_text_size</item> + <item name="android:textStyle">italic</item> + <item name="android:paddingRight">20dp</item> + <item name="android:minHeight">56dp</item> </style> - <style name="TranscriptionQualityRatingLink"> - <item name="android:textColor">@color/call_log_voicemail_transcript_rating_color</item> - <item name="android:textSize">@dimen/call_log_voicemail_transcription_text_size</item> + <style name="TranscriptionQualityRatingIcon"> <item name="android:paddingTop">8dp</item> <item name="android:paddingBottom">8dp</item> - <item name="android:paddingLeft">12dp</item> - <item name="android:paddingRight">12dp</item> - <item name="android:minHeight">48dp</item> + <item name="android:paddingLeft">16dp</item> + <item name="android:paddingRight">16dp</item> + <item name="android:minHeight">56dp</item> </style> + + <style name="PromoLinkStyle"> + <item name="android:textColor">@color/dialer_theme_color</item> + <item name="android:fontFamily">"sans-serif-medium"</item> + </style> + </resources> 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 @@ <dimen name="call_log_primary_text_size">16sp</dimen> <dimen name="call_log_detail_text_size">12sp</dimen> <dimen name="call_log_day_group_heading_size">14sp</dimen> - <dimen name="call_log_voicemail_transcription_text_size">14sp</dimen> + <dimen name="call_log_voicemail_transcription_text_size">16sp</dimen> <!-- Height of the call log actions section for each call log entry --> <dimen name="call_log_action_height">48dp</dimen> <dimen name="call_log_day_group_padding_top">15dp</dimen> |