1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.dialer.historyitemactions; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.net.Uri; 22 import android.provider.ContactsContract; 23 import android.support.annotation.Nullable; 24 import android.text.TextUtils; 25 import android.widget.Toast; 26 import com.android.dialer.DialerPhoneNumber; 27 import com.android.dialer.blockreportspam.BlockReportSpamDialogInfo; 28 import com.android.dialer.blockreportspam.ShowBlockReportSpamDialogNotifier; 29 import com.android.dialer.clipboard.ClipboardUtils; 30 import com.android.dialer.util.IntentUtil; 31 import com.android.dialer.util.UriUtils; 32 import com.google.common.base.Optional; 33 import java.util.ArrayList; 34 import java.util.List; 35 import java.util.Locale; 36 37 /** 38 * Modules for the bottom sheet that are shared between NewVoicemailFragment and NewCallLogFragment 39 */ 40 @SuppressWarnings("Guava") 41 public class SharedModules { 42 createModuleForAddingToContacts( Context context, DialerPhoneNumber dialerPhoneNumber, String name, String lookupUri, boolean isBlocked, boolean isSpam)43 public static Optional<HistoryItemActionModule> createModuleForAddingToContacts( 44 Context context, 45 DialerPhoneNumber dialerPhoneNumber, 46 String name, 47 String lookupUri, 48 boolean isBlocked, 49 boolean isSpam) { 50 // Skip showing the menu item for a spam/blocked number. 51 if (isBlocked || isSpam) { 52 return Optional.absent(); 53 } 54 55 // Skip showing the menu item for existing contacts. 56 if (isExistingContact(lookupUri)) { 57 return Optional.absent(); 58 } 59 60 // Skip showing the menu item if there is no number. 61 String normalizedNumber = dialerPhoneNumber.getNormalizedNumber(); 62 if (TextUtils.isEmpty(normalizedNumber)) { 63 return Optional.absent(); 64 } 65 66 Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT); 67 intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE); 68 intent.putExtra(ContactsContract.Intents.Insert.PHONE, normalizedNumber); 69 70 if (!TextUtils.isEmpty(name)) { 71 intent.putExtra(ContactsContract.Intents.Insert.NAME, name); 72 } 73 74 return Optional.of( 75 new IntentModule( 76 context, 77 intent, 78 R.string.add_to_contacts, 79 R.drawable.quantum_ic_person_add_vd_theme_24)); 80 } 81 82 /** 83 * Lookup URIs are currently fetched from the cached column of the system call log. This URI 84 * contains encoded information for non-contacts for the purposes of populating contact cards. 85 * 86 * <p>We infer whether a contact is existing or not by checking if the lookup URI is "encoded" or 87 * not. 88 * 89 * <p>TODO(zachh): We should revisit this once the contact URI is no longer being read from the 90 * cached column in the system database, in case we decide not to overload the column. 91 */ isExistingContact(@ullable String lookupUri)92 private static boolean isExistingContact(@Nullable String lookupUri) { 93 return !TextUtils.isEmpty(lookupUri) && !UriUtils.isEncodedContactUri(Uri.parse(lookupUri)); 94 } 95 createModuleForSendingTextMessage( Context context, String normalizedNumber, boolean isBlocked)96 public static Optional<HistoryItemActionModule> createModuleForSendingTextMessage( 97 Context context, String normalizedNumber, boolean isBlocked) { 98 // Don't show the option to send a text message if the number is blocked. 99 if (isBlocked) { 100 return Optional.absent(); 101 } 102 103 // TODO(zachh): There are some conditions where this module should not be shown; consider 104 // voicemail, business numbers, etc. 105 106 return !TextUtils.isEmpty(normalizedNumber) 107 ? Optional.of( 108 new IntentModule( 109 context, 110 IntentUtil.getSendSmsIntent(normalizedNumber), 111 R.string.send_a_message, 112 R.drawable.quantum_ic_message_vd_theme_24)) 113 : Optional.absent(); 114 } 115 116 /** 117 * Create modules related to blocking/unblocking a number and/or reporting it as spam/not spam. 118 */ createModulesHandlingBlockedOrSpamNumber( Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo, boolean isBlocked, boolean isSpam)119 public static List<HistoryItemActionModule> createModulesHandlingBlockedOrSpamNumber( 120 Context context, 121 BlockReportSpamDialogInfo blockReportSpamDialogInfo, 122 boolean isBlocked, 123 boolean isSpam) { 124 List<HistoryItemActionModule> modules = new ArrayList<>(); 125 126 // For a spam number, add two options: 127 // (1) "Not spam" and "Block", or 128 // (2) "Not spam" and "Unblock". 129 if (isSpam) { 130 modules.add(createModuleForMarkingNumberAsNonSpam(context, blockReportSpamDialogInfo)); 131 modules.add( 132 createModuleForBlockingOrUnblockingNumber(context, blockReportSpamDialogInfo, isBlocked)); 133 return modules; 134 } 135 136 // For a blocked non-spam number, add "Unblock" option. 137 if (isBlocked) { 138 modules.add( 139 createModuleForBlockingOrUnblockingNumber(context, blockReportSpamDialogInfo, isBlocked)); 140 return modules; 141 } 142 143 // For a number that is neither a spam number nor blocked, add "Block/Report spam" option. 144 modules.add( 145 createModuleForBlockingNumberAndOptionallyReportingSpam( 146 context, blockReportSpamDialogInfo)); 147 return modules; 148 } 149 150 /** Create "Not spam" module. */ createModuleForMarkingNumberAsNonSpam( Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo)151 private static HistoryItemActionModule createModuleForMarkingNumberAsNonSpam( 152 Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { 153 return new HistoryItemActionModule() { 154 @Override 155 public int getStringId() { 156 return R.string.not_spam; 157 } 158 159 @Override 160 public int getDrawableId() { 161 return R.drawable.quantum_ic_report_off_vd_theme_24; 162 } 163 164 @Override 165 public boolean onClick() { 166 ShowBlockReportSpamDialogNotifier.notifyShowDialogToReportNotSpam( 167 context, blockReportSpamDialogInfo); 168 return true; // Close the bottom sheet. 169 } 170 }; 171 } 172 173 private static HistoryItemActionModule createModuleForBlockingOrUnblockingNumber( 174 Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo, boolean isBlocked) { 175 return new HistoryItemActionModule() { 176 @Override 177 public int getStringId() { 178 return isBlocked ? R.string.unblock_number : R.string.block_number; 179 } 180 181 @Override 182 public int getDrawableId() { 183 return isBlocked 184 ? R.drawable.ic_unblock // TODO(a bug): use a vector icon 185 : R.drawable.quantum_ic_block_vd_theme_24; 186 } 187 188 @Override 189 public boolean onClick() { 190 // TODO(a bug): implement this method. 191 Toast.makeText( 192 context, 193 String.format( 194 Locale.ENGLISH, 195 "TODO: " + (isBlocked ? "Unblock " : "Block ") + " number %s.", 196 blockReportSpamDialogInfo.getNormalizedNumber()), 197 Toast.LENGTH_SHORT) 198 .show(); 199 return true; // Close the bottom sheet. 200 } 201 }; 202 } 203 204 /** Create "Block/Report spam" module */ 205 private static HistoryItemActionModule createModuleForBlockingNumberAndOptionallyReportingSpam( 206 Context context, BlockReportSpamDialogInfo blockReportSpamDialogInfo) { 207 return new HistoryItemActionModule() { 208 @Override 209 public int getStringId() { 210 return R.string.block_and_optionally_report_spam; 211 } 212 213 @Override 214 public int getDrawableId() { 215 return R.drawable.quantum_ic_block_vd_theme_24; 216 } 217 218 @Override 219 public boolean onClick() { 220 ShowBlockReportSpamDialogNotifier.notifyShowDialogToBlockNumberAndOptionallyReportSpam( 221 context, blockReportSpamDialogInfo); 222 return true; // Close the bottom sheet. 223 } 224 }; 225 } 226 227 public static Optional<HistoryItemActionModule> createModuleForCopyingNumber( 228 Context context, String normalizedNumber) { 229 if (TextUtils.isEmpty(normalizedNumber)) { 230 return Optional.absent(); 231 } 232 return Optional.of( 233 new HistoryItemActionModule() { 234 @Override 235 public int getStringId() { 236 return R.string.copy_number; 237 } 238 239 @Override 240 public int getDrawableId() { 241 return R.drawable.quantum_ic_content_copy_vd_theme_24; 242 } 243 244 @Override 245 public boolean onClick() { 246 ClipboardUtils.copyText(context, null, normalizedNumber, true); 247 return false; 248 } 249 }); 250 } 251 } 252