summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/historyitemactions
diff options
context:
space:
mode:
authorlinyuh <linyuh@google.com>2018-02-27 16:49:39 -0800
committerCopybara-Service <copybara-piper@google.com>2018-02-27 17:06:14 -0800
commit4ef51165ffd5e2b9fc804b18d5bb8a49937cd44d (patch)
treebd56f76a885f5e37acb7d7e019c6dd7570805188 /java/com/android/dialer/historyitemactions
parent311c5250451bf5985761690568e3e70ca3b28664 (diff)
Internal cleanup for the new UI's bottom sheet.
Test: Existing tests PiperOrigin-RevId: 187254014 Change-Id: I8a57b632d45e87ad075eb8bbb25180858e890f08
Diffstat (limited to 'java/com/android/dialer/historyitemactions')
-rw-r--r--java/com/android/dialer/historyitemactions/AndroidManifest.xml16
-rw-r--r--java/com/android/dialer/historyitemactions/DividerModule.java41
-rw-r--r--java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java137
-rw-r--r--java/com/android/dialer/historyitemactions/HistoryItemActionModule.java37
-rw-r--r--java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java73
-rw-r--r--java/com/android/dialer/historyitemactions/IntentModule.java96
-rw-r--r--java/com/android/dialer/historyitemactions/SharedModules.java284
-rw-r--r--java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.pngbin0 -> 1034 bytes
-rw-r--r--java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml54
-rw-r--r--java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml23
-rw-r--r--java/com/android/dialer/historyitemactions/res/layout/module_layout.xml40
-rw-r--r--java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml24
-rw-r--r--java/com/android/dialer/historyitemactions/res/values/dimens.xml20
-rw-r--r--java/com/android/dialer/historyitemactions/res/values/strings.xml47
14 files changed, 892 insertions, 0 deletions
diff --git a/java/com/android/dialer/historyitemactions/AndroidManifest.xml b/java/com/android/dialer/historyitemactions/AndroidManifest.xml
new file mode 100644
index 000000000..4d302685f
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<manifest package="com.android.dialer.historyitemactions"/>
diff --git a/java/com/android/dialer/historyitemactions/DividerModule.java b/java/com/android/dialer/historyitemactions/DividerModule.java
new file mode 100644
index 000000000..a5ca62abe
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/DividerModule.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.dialer.historyitemactions;
+
+import com.android.dialer.common.Assert;
+
+/**
+ * A module that inserts a grey line divider into {@link HistoryItemActionModule}. Layout it
+ * provided in R.layout.divider_layout.xml
+ */
+public final class DividerModule implements HistoryItemActionModule {
+
+ @Override
+ public int getStringId() {
+ throw Assert.createUnsupportedOperationFailException();
+ }
+
+ @Override
+ public int getDrawableId() {
+ throw Assert.createUnsupportedOperationFailException();
+ }
+
+ @Override
+ public boolean onClick() {
+ throw Assert.createUnsupportedOperationFailException();
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
new file mode 100644
index 000000000..47aa1003f
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionBottomSheet.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.dialer.historyitemactions;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.design.widget.BottomSheetDialog;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import com.android.dialer.common.Assert;
+import com.android.dialer.glidephotomanager.GlidePhotoManager;
+import java.util.List;
+
+/**
+ * {@link BottomSheetDialog} used to show a list of actions in a bottom sheet menu.
+ *
+ * <p>{@link #show(Context, HistoryItemPrimaryActionInfo, List, GlidePhotoManager)} should be used
+ * to create and display the menu. Modules are built using {@link HistoryItemActionModule} and some
+ * defaults are provided by {@link IntentModule} and {@link DividerModule}.
+ */
+public class HistoryItemActionBottomSheet extends BottomSheetDialog implements OnClickListener {
+
+ private final List<HistoryItemActionModule> modules;
+ private final HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo;
+ private final GlidePhotoManager glidePhotoManager;
+
+ private HistoryItemActionBottomSheet(
+ Context context,
+ HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo,
+ List<HistoryItemActionModule> modules,
+ GlidePhotoManager glidePhotoManager) {
+ super(context);
+ this.modules = modules;
+ this.historyItemPrimaryActionInfo = historyItemPrimaryActionInfo;
+ this.glidePhotoManager = glidePhotoManager;
+ setContentView(LayoutInflater.from(context).inflate(R.layout.sheet_layout, null));
+ }
+
+ public static HistoryItemActionBottomSheet show(
+ Context context,
+ HistoryItemPrimaryActionInfo historyItemPrimaryActionInfo,
+ List<HistoryItemActionModule> modules,
+ GlidePhotoManager glidePhotoManager) {
+ HistoryItemActionBottomSheet sheet =
+ new HistoryItemActionBottomSheet(
+ context, historyItemPrimaryActionInfo, modules, glidePhotoManager);
+ sheet.show();
+ return sheet;
+ }
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ LinearLayout container = Assert.isNotNull(findViewById(R.id.action_container));
+ container.addView(getContactView(container));
+
+ for (HistoryItemActionModule module : modules) {
+ if (module instanceof DividerModule) {
+ container.addView(getDividerView(container));
+ } else {
+ container.addView(getModuleView(container, module));
+ }
+ }
+ }
+
+ private View getContactView(ViewGroup container) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ View contactView = inflater.inflate(R.layout.contact_layout, container, false);
+
+ // TODO(zachh): The contact image should be badged with a video icon if it is for a video call.
+ glidePhotoManager.loadQuickContactBadge(
+ contactView.findViewById(R.id.quick_contact_photo),
+ historyItemPrimaryActionInfo.photoInfo());
+
+ TextView primaryTextView = contactView.findViewById(R.id.primary_text);
+ TextView secondaryTextView = contactView.findViewById(R.id.secondary_text);
+
+ primaryTextView.setText(historyItemPrimaryActionInfo.primaryText());
+ if (!TextUtils.isEmpty(historyItemPrimaryActionInfo.secondaryText())) {
+ secondaryTextView.setText(historyItemPrimaryActionInfo.secondaryText());
+ } else {
+ secondaryTextView.setVisibility(View.GONE);
+ secondaryTextView.setText(null);
+ }
+ if (historyItemPrimaryActionInfo.intent() != null) {
+ contactView.setOnClickListener(
+ (view) -> {
+ getContext().startActivity(historyItemPrimaryActionInfo.intent());
+ dismiss();
+ });
+ }
+ return contactView;
+ }
+
+ private View getDividerView(ViewGroup container) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ return inflater.inflate(R.layout.divider_layout, container, false);
+ }
+
+ private View getModuleView(ViewGroup container, HistoryItemActionModule module) {
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ View moduleView = inflater.inflate(R.layout.module_layout, container, false);
+ ((TextView) moduleView.findViewById(R.id.module_text)).setText(module.getStringId());
+ ((ImageView) moduleView.findViewById(R.id.module_image))
+ .setImageResource(module.getDrawableId());
+ moduleView.setOnClickListener(this);
+ moduleView.setTag(module);
+ return moduleView;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (((HistoryItemActionModule) view.getTag()).onClick()) {
+ dismiss();
+ }
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/HistoryItemActionModule.java b/java/com/android/dialer/historyitemactions/HistoryItemActionModule.java
new file mode 100644
index 000000000..d64cbca53
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/HistoryItemActionModule.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.dialer.historyitemactions;
+
+import android.support.annotation.DrawableRes;
+import android.support.annotation.StringRes;
+
+/**
+ * Modules used to build {@link HistoryItemActionBottomSheet}.
+ *
+ * <p>A history item is one that is displayed in the call log or the voicemail fragment.
+ */
+public interface HistoryItemActionModule {
+
+ @StringRes
+ int getStringId();
+
+ @DrawableRes
+ int getDrawableId();
+
+ /** @return true if the bottom sheet should close, false otherwise */
+ boolean onClick();
+}
diff --git a/java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java b/java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java
new file mode 100644
index 000000000..f4338ce7a
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/HistoryItemPrimaryActionInfo.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package com.android.dialer.historyitemactions;
+
+import android.content.Intent;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.glidephotomanager.PhotoInfo;
+import com.google.auto.value.AutoValue;
+
+/**
+ * Contains information necessary to construct the primary action for a history item's bottom sheet.
+ *
+ * <p>A history item is one that is displayed in the call log or the voicemail fragment.
+ */
+@AutoValue
+public abstract class HistoryItemPrimaryActionInfo {
+
+ @Nullable
+ public abstract DialerPhoneNumber number();
+
+ @NonNull
+ public abstract PhotoInfo photoInfo();
+
+ @Nullable
+ public abstract CharSequence primaryText();
+
+ @Nullable
+ public abstract CharSequence secondaryText();
+
+ /**
+ * The intent to fire when the user clicks the top row of the bottom sheet. Null if no action
+ * should occur (e.g. if the number is unknown).
+ */
+ @Nullable
+ public abstract Intent intent();
+
+ // TODO(zachh): Add SIM info here if should be shown in bottom sheet.
+
+ /** Builder for {@link HistoryItemPrimaryActionInfo}. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+ public abstract Builder setNumber(@Nullable DialerPhoneNumber dialerPhoneNumber);
+
+ public abstract Builder setPhotoInfo(@NonNull PhotoInfo photoInfo);
+
+ public abstract Builder setPrimaryText(@Nullable CharSequence primaryText);
+
+ public abstract Builder setSecondaryText(@Nullable CharSequence secondaryText);
+
+ public abstract Builder setIntent(@Nullable Intent intent);
+
+ public abstract HistoryItemPrimaryActionInfo build();
+ }
+
+ public static Builder builder() {
+ return new AutoValue_HistoryItemPrimaryActionInfo.Builder();
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/IntentModule.java b/java/com/android/dialer/historyitemactions/IntentModule.java
new file mode 100644
index 000000000..dfe9bb064
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/IntentModule.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+package com.android.dialer.historyitemactions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.telecom.PhoneAccountHandle;
+import com.android.dialer.callintent.CallInitiationType.Type;
+import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.precall.PreCall;
+import com.android.dialer.util.DialerUtils;
+
+/**
+ * {@link HistoryItemActionModule} useful for making easy to build modules based on starting an
+ * intent.
+ */
+public class IntentModule implements HistoryItemActionModule {
+
+ private final Context context;
+ private final Intent intent;
+ private final @StringRes int text;
+ private final @DrawableRes int image;
+
+ public IntentModule(Context context, Intent intent, @StringRes int text, @DrawableRes int image) {
+ this.context = context;
+ this.intent = intent;
+ this.text = text;
+ this.image = image;
+ }
+
+ @Override
+ public int getStringId() {
+ return text;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return image;
+ }
+
+ @Override
+ public boolean onClick() {
+ DialerUtils.startActivityWithErrorToast(context, intent);
+ return true;
+ }
+
+ public static IntentModule newCallModule(
+ Context context,
+ String number,
+ @Nullable PhoneAccountHandle phoneAccountHandle,
+ Type initiationType) {
+ // TODO(zachh): Support post-dial digits; consider using DialerPhoneNumber.
+ return new IntentModule(
+ context,
+ PreCall.getIntent(
+ context,
+ new CallIntentBuilder(number, initiationType)
+ .setPhoneAccountHandle(phoneAccountHandle)),
+ R.string.voice_call,
+ R.drawable.quantum_ic_call_white_24);
+ }
+
+ public static IntentModule newVideoCallModule(
+ Context context,
+ String number,
+ @Nullable PhoneAccountHandle phoneAccountHandle,
+ Type initiationType) {
+ // TODO(zachh): Support post-dial digits; consider using DialerPhoneNumber.
+ return new IntentModule(
+ context,
+ PreCall.getIntent(
+ context,
+ new CallIntentBuilder(number, initiationType)
+ .setPhoneAccountHandle(phoneAccountHandle)
+ .setIsVideoCall(true)),
+ R.string.video_call,
+ R.drawable.quantum_ic_videocam_white_24);
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/SharedModules.java b/java/com/android/dialer/historyitemactions/SharedModules.java
new file mode 100644
index 000000000..7cfee37bb
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/SharedModules.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2017 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
+ */
+
+package com.android.dialer.historyitemactions;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.widget.Toast;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier;
+import com.android.dialer.clipboard.ClipboardUtils;
+import com.android.dialer.logging.ReportingLocation;
+import com.android.dialer.util.IntentUtil;
+import com.android.dialer.util.UriUtils;
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment
+ */
+@SuppressWarnings("Guava")
+public class SharedModules {
+
+ public static Optional<HistoryItemActionModule> createModuleForAddingToContacts(
+ Context context,
+ DialerPhoneNumber dialerPhoneNumber,
+ String name,
+ String lookupUri,
+ boolean isBlocked,
+ boolean isSpam) {
+ // Skip showing the menu item for a spam/blocked number.
+ if (isBlocked || isSpam) {
+ return Optional.absent();
+ }
+
+ // Skip showing the menu item for existing contacts.
+ if (isExistingContact(lookupUri)) {
+ return Optional.absent();
+ }
+
+ // Skip showing the menu item if there is no number.
+ String normalizedNumber = dialerPhoneNumber.getNormalizedNumber();
+ if (TextUtils.isEmpty(normalizedNumber)) {
+ return Optional.absent();
+ }
+
+ Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+ intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+ intent.putExtra(ContactsContract.Intents.Insert.PHONE, normalizedNumber);
+
+ if (!TextUtils.isEmpty(name)) {
+ intent.putExtra(ContactsContract.Intents.Insert.NAME, name);
+ }
+
+ return Optional.of(
+ new IntentModule(
+ context,
+ intent,
+ R.string.add_to_contacts,
+ R.drawable.quantum_ic_person_add_vd_theme_24));
+ }
+
+ /**
+ * Lookup URIs are currently fetched from the cached column of the system call log. This URI
+ * contains encoded information for non-contacts for the purposes of populating contact cards.
+ *
+ * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or
+ * not.
+ *
+ * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the
+ * cached column in the system database, in case we decide not to overload the column.
+ */
+ private static boolean isExistingContact(@Nullable String lookupUri) {
+ return !TextUtils.isEmpty(lookupUri) && !UriUtils.isEncodedContactUri(Uri.parse(lookupUri));
+ }
+
+ public static Optional<HistoryItemActionModule> createModuleForSendingTextMessage(
+ Context context, String normalizedNumber, boolean isBlocked) {
+ // Don't show the option to send a text message if the number is blocked.
+ if (isBlocked) {
+ return Optional.absent();
+ }
+
+ // TODO(zachh): There are some conditions where this module should not be shown; consider
+ // voicemail, business numbers, etc.
+
+ return !TextUtils.isEmpty(normalizedNumber)
+ ? Optional.of(
+ new IntentModule(
+ context,
+ IntentUtil.getSendSmsIntent(normalizedNumber),
+ R.string.send_a_message,
+ R.drawable.quantum_ic_message_vd_theme_24))
+ : Optional.absent();
+ }
+
+ /**
+ * Add modules related to blocking/unblocking a number and/or reporting it as spam/not spam.
+ *
+ * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
+ * @param countryIso The ISO 3166-1 two letters country code for the number
+ * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+ * @param reportingLocation The location where the number is reported. See {@link
+ * ReportingLocation.Type}.
+ */
+ public static List<HistoryItemActionModule> createModulesHandlingBlockedOrSpamNumber(
+ Context context,
+ String normalizedNumber,
+ String countryIso,
+ int callType,
+ boolean isBlocked,
+ boolean isSpam,
+ ReportingLocation.Type reportingLocation) {
+ List<HistoryItemActionModule> modules = new ArrayList<>();
+
+ // For a spam number, add two options:
+ // (1) "Not spam" and "Block", or
+ // (2) "Not spam" and "Unblock".
+ if (isSpam) {
+ modules.add(
+ createModuleForMarkingNumberAsNonSpam(
+ context, normalizedNumber, countryIso, callType, reportingLocation));
+ modules.add(createModuleForBlockingOrUnblockingNumber(context, normalizedNumber, isBlocked));
+ return modules;
+ }
+
+ // For a blocked non-spam number, add "Unblock" option.
+ if (isBlocked) {
+ modules.add(createModuleForBlockingOrUnblockingNumber(context, normalizedNumber, isBlocked));
+ return modules;
+ }
+
+ // For a number that is neither a spam number nor blocked, add "Block/Report spam" option.
+ modules.add(
+ createModuleForBlockingNumberAndOptionallyReportingSpam(
+ context, normalizedNumber, countryIso, callType, reportingLocation));
+ return modules;
+ }
+
+ /**
+ * Add "Not spam" module.
+ *
+ * @param normalizedNumber The number to be marked as not spam
+ * @param countryIso The ISO 3166-1 two letters country code for the number
+ * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+ * @param reportingLocation The location where the number is reported. See {@link
+ * ReportingLocation.Type}.
+ */
+ private static HistoryItemActionModule createModuleForMarkingNumberAsNonSpam(
+ Context context,
+ String normalizedNumber,
+ String countryIso,
+ int callType,
+ ReportingLocation.Type reportingLocation) {
+ return new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.not_spam;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_report_off_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam(
+ context, normalizedNumber, countryIso, callType, reportingLocation);
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ private static HistoryItemActionModule createModuleForBlockingOrUnblockingNumber(
+ Context context, String normalizedNumber, boolean isBlocked) {
+ return new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return isBlocked ? R.string.unblock_number : R.string.block_number;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return isBlocked
+ ? R.drawable.ic_unblock // TODO(a bug): use a vector icon
+ : R.drawable.quantum_ic_block_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ // TODO(a bug): implement this method.
+ Toast.makeText(
+ context,
+ String.format(
+ Locale.ENGLISH,
+ "TODO: " + (isBlocked ? "Unblock " : "Block ") + " number %s.",
+ normalizedNumber),
+ Toast.LENGTH_SHORT)
+ .show();
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ /**
+ * Add "Block/Report spam" module
+ *
+ * @param normalizedNumber The number to be blocked / unblocked / marked as spam/not spam
+ * @param countryIso The ISO 3166-1 two letters country code for the number
+ * @param callType Call type defined in {@link android.provider.CallLog.Calls}
+ * @param reportingLocation The location where the number is reported. See {@link
+ * ReportingLocation.Type}.
+ */
+ private static HistoryItemActionModule createModuleForBlockingNumberAndOptionallyReportingSpam(
+ Context context,
+ String normalizedNumber,
+ String countryIso,
+ int callType,
+ ReportingLocation.Type reportingLocation) {
+ return new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.block_and_optionally_report_spam;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_block_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam(
+ context, normalizedNumber, countryIso, callType, reportingLocation);
+ return true; // Close the bottom sheet.
+ }
+ };
+ }
+
+ public static Optional<HistoryItemActionModule> createModuleForCopyingNumber(
+ Context context, String normalizedNumber) {
+ if (TextUtils.isEmpty(normalizedNumber)) {
+ return Optional.absent();
+ }
+ return Optional.of(
+ new HistoryItemActionModule() {
+ @Override
+ public int getStringId() {
+ return R.string.copy_number;
+ }
+
+ @Override
+ public int getDrawableId() {
+ return R.drawable.quantum_ic_content_copy_vd_theme_24;
+ }
+
+ @Override
+ public boolean onClick() {
+ ClipboardUtils.copyText(context, null, normalizedNumber, true);
+ return false;
+ }
+ });
+ }
+}
diff --git a/java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.png b/java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.png
new file mode 100644
index 000000000..01551e2fc
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/drawable-xxxhdpi/ic_unblock.png
Binary files differ
diff --git a/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
new file mode 100644
index 000000000..4deef3e07
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/layout/contact_layout.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="12dp"
+ android:layout_marginEnd="8dp"
+ android:gravity="center_vertical"
+ android:orientation="horizontal">
+
+ <QuickContactBadge
+ android:id="@+id/quick_contact_photo"
+ android:layout_width="@dimen/contact_actions_image_size"
+ android:layout_height="@dimen/contact_actions_image_size"
+ android:layout_marginStart="@dimen/contact_actions_image_margin"
+ android:layout_marginEnd="@dimen/contact_actions_image_margin"
+ android:padding="4dp"
+ android:focusable="true"/>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/primary_text"
+ style="@style/PrimaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <TextView
+ android:id="@+id/secondary_text"
+ style="@style/SecondaryText"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="2dp"/>
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml
new file mode 100644
index 000000000..fdee50e48
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/layout/divider_layout.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<View
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:background="#12000000"/>
diff --git a/java/com/android/dialer/historyitemactions/res/layout/module_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/module_layout.xml
new file mode 100644
index 000000000..9aee67937
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/layout/module_layout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/module_container"
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/selectableItemBackground">
+
+ <ImageView
+ android:id="@+id/module_image"
+ android:layout_width="@dimen/contact_actions_image_size"
+ android:layout_height="@dimen/contact_actions_image_size"
+ android:layout_marginStart="@dimen/contact_actions_image_margin"
+ android:layout_marginEnd="@dimen/contact_actions_image_margin"
+ android:tint="@color/dialer_secondary_text_color"
+ android:scaleType="center"/>
+
+ <TextView
+ android:id="@+id/module_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ style="@style/PrimaryText"/>
+</LinearLayout> \ No newline at end of file
diff --git a/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml b/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
new file mode 100644
index 000000000..6984367bf
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/layout/sheet_layout.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/action_container"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="4dp"
+ android:paddingBottom="8dp"/>
diff --git a/java/com/android/dialer/historyitemactions/res/values/dimens.xml b/java/com/android/dialer/historyitemactions/res/values/dimens.xml
new file mode 100644
index 000000000..47bf804ac
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+<resources>
+ <dimen name="contact_actions_image_size">48dp</dimen>
+ <dimen name="contact_actions_image_margin">12dp</dimen>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/historyitemactions/res/values/strings.xml b/java/com/android/dialer/historyitemactions/res/values/strings.xml
new file mode 100644
index 000000000..4d598a930
--- /dev/null
+++ b/java/com/android/dialer/historyitemactions/res/values/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+
+<resources>
+ <!-- Option shown in call log/voicemail menu to make a voice call [CHAR LIMIT=30] -->
+ <string name="voice_call">Voice call</string>
+
+ <!-- Option shown in a call log/voicemail menu to make a video call [CHAR LIMIT=30] -->
+ <string name="video_call">Video call</string>
+
+ <!-- Option shown in call log menu/voicemail to add the phone number from an entry to an existing contact
+ (also provides option to create a new contact from the number). [CHAR LIMIT=30] -->
+ <string name="add_to_contacts">Add contact</string>
+
+ <!-- Options shown in call log/voicemail menu to send a SMS to the number represented by the call log/voicemailentry.
+ [CHAR LIMIT=30] -->
+ <string name="send_a_message">Message</string>
+
+ <!-- Options shown in call log/voicemail menu to mark a number as non-spam. [CHAR LIMIT=30] -->
+ <string name="not_spam">Not spam</string>
+
+ <!-- Options shown in a call log/voicemail menu to block a number. [CHAR LIMIT=30] -->
+ <string name="block_number">Block</string>
+
+ <!-- Options shown in a call log/voicemail menu to unblock a number. [CHAR LIMIT=30] -->
+ <string name="unblock_number">Unblock</string>
+
+ <!-- Options shown in a call log/voicemail menu to block a number and/or report it as spam. [CHAR LIMIT=30] -->
+ <string name="block_and_optionally_report_spam">Block/Report spam</string>
+
+ <!-- Option displayed in call log/voicemail menu to copy phone number. [CHAR LIMIT=30] -->
+ <string name="copy_number">Copy number</string>
+</resources> \ No newline at end of file