1 /* 2 * Copyright (C) 2016 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.blockreportspam; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.os.Bundle; 24 import android.support.annotation.Nullable; 25 import android.support.v4.app.DialogFragment; 26 import android.support.v7.app.AlertDialog; 27 import android.view.View; 28 import android.widget.CheckBox; 29 import android.widget.TextView; 30 import com.android.dialer.blocking.FilteredNumberCompat; 31 32 /** Creates dialog fragments to block a number and/or report it as spam/not spam. */ 33 public final class BlockReportSpamDialogs { 34 35 public static final String BLOCK_REPORT_SPAM_DIALOG_TAG = "BlockReportSpamDialog"; 36 public static final String BLOCK_DIALOG_TAG = "BlockDialog"; 37 public static final String UNBLOCK_DIALOG_TAG = "UnblockDialog"; 38 public static final String NOT_SPAM_DIALOG_TAG = "NotSpamDialog"; 39 40 /** Creates a dialog with the default cancel button listener (which dismisses the dialog). */ createDialogBuilder( Activity activity, final DialogFragment fragment)41 private static AlertDialog.Builder createDialogBuilder( 42 Activity activity, final DialogFragment fragment) { 43 return new AlertDialog.Builder(activity) 44 .setCancelable(true) 45 .setNegativeButton(android.R.string.cancel, (dialog, which) -> fragment.dismiss()); 46 } 47 48 /** 49 * Creates a generic click listener which dismisses the fragment and then calls the actual 50 * listener. 51 */ createGenericOnClickListener( final DialogFragment fragment, final OnConfirmListener listener)52 private static DialogInterface.OnClickListener createGenericOnClickListener( 53 final DialogFragment fragment, final OnConfirmListener listener) { 54 return (dialog, which) -> { 55 fragment.dismiss(); 56 listener.onClick(); 57 }; 58 } 59 getBlockMessage(Context context)60 private static String getBlockMessage(Context context) { 61 String message; 62 if (FilteredNumberCompat.useNewFiltering(context)) { 63 message = context.getString(R.string.block_number_confirmation_message_new_filtering); 64 } else { 65 message = context.getString(R.string.block_report_number_alert_details); 66 } 67 return message; 68 } 69 70 /** 71 * Positive listener for the "Block/Report spam" dialog {@link 72 * DialogFragmentForBlockingNumberAndOptionallyReportingAsSpam}. 73 */ 74 public interface OnSpamDialogClickListener { 75 76 /** 77 * Called when the user clicks on the positive button of the "Block/Report spam" dialog. 78 * 79 * @param isSpamChecked Whether the spam checkbox is checked. 80 */ onClick(boolean isSpamChecked)81 void onClick(boolean isSpamChecked); 82 } 83 84 /** Positive listener for dialogs other than the "Block/Report spam" dialog. */ 85 public interface OnConfirmListener { 86 87 /** Called when the user clicks on the positive button of the dialog. */ onClick()88 void onClick(); 89 } 90 91 /** Contains common attributes shared among all dialog fragments. */ 92 private abstract static class CommonDialogsFragment extends DialogFragment { 93 94 /** The number to display in the dialog title. */ 95 protected String displayNumber; 96 97 /** Listener for the positive button. */ 98 protected OnConfirmListener positiveListener; 99 100 /** Listener for when the dialog is dismissed. */ 101 @Nullable protected DialogInterface.OnDismissListener dismissListener; 102 103 @Override onDismiss(DialogInterface dialog)104 public void onDismiss(DialogInterface dialog) { 105 if (dismissListener != null) { 106 dismissListener.onDismiss(dialog); 107 } 108 super.onDismiss(dialog); 109 } 110 111 @Override onPause()112 public void onPause() { 113 // The dialog is dismissed onPause, i.e. rotation. 114 dismiss(); 115 dismissListener = null; 116 positiveListener = null; 117 displayNumber = null; 118 super.onPause(); 119 } 120 } 121 122 /** 123 * Dialog for blocking a number and optionally reporting it as spam. 124 * 125 * <p>This dialog is for a number that is neither blocked nor marked as spam. It has a checkbox 126 * that allows the user to report a number as spam when they block it. 127 */ 128 public static class DialogFragmentForBlockingNumberAndOptionallyReportingAsSpam 129 extends CommonDialogsFragment { 130 131 /** Called when dialog positive button is pressed. */ 132 private OnSpamDialogClickListener onSpamDialogClickListener; 133 134 /** Whether the mark as spam checkbox is checked before displaying the dialog. */ 135 private boolean spamChecked; 136 newInstance( String displayNumber, boolean spamChecked, OnSpamDialogClickListener onSpamDialogClickListener, @Nullable DialogInterface.OnDismissListener dismissListener)137 public static DialogFragment newInstance( 138 String displayNumber, 139 boolean spamChecked, 140 OnSpamDialogClickListener onSpamDialogClickListener, 141 @Nullable DialogInterface.OnDismissListener dismissListener) { 142 DialogFragmentForBlockingNumberAndOptionallyReportingAsSpam fragment = 143 new DialogFragmentForBlockingNumberAndOptionallyReportingAsSpam(); 144 fragment.spamChecked = spamChecked; 145 fragment.displayNumber = displayNumber; 146 fragment.onSpamDialogClickListener = onSpamDialogClickListener; 147 fragment.dismissListener = dismissListener; 148 return fragment; 149 } 150 151 @Override onCreateDialog(Bundle savedInstanceState)152 public Dialog onCreateDialog(Bundle savedInstanceState) { 153 super.onCreateDialog(savedInstanceState); 154 View dialogView = View.inflate(getActivity(), R.layout.block_report_spam_dialog, null); 155 final CheckBox isSpamCheckbox = 156 (CheckBox) dialogView.findViewById(R.id.report_number_as_spam_action); 157 // Listen for changes on the checkbox and update if orientation changes 158 isSpamCheckbox.setChecked(spamChecked); 159 isSpamCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> spamChecked = isChecked); 160 161 TextView details = (TextView) dialogView.findViewById(R.id.block_details); 162 details.setText(getBlockMessage(getContext())); 163 164 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 165 Dialog blockReportSpamDialog = 166 alertDialogBuilder 167 .setView(dialogView) 168 .setTitle(getString(R.string.block_report_number_alert_title, displayNumber)) 169 .setPositiveButton( 170 R.string.block_number_ok, 171 (dialog, which) -> { 172 dismiss(); 173 onSpamDialogClickListener.onClick(isSpamCheckbox.isChecked()); 174 }) 175 .create(); 176 blockReportSpamDialog.setCanceledOnTouchOutside(true); 177 return blockReportSpamDialog; 178 } 179 } 180 181 /** 182 * Dialog for blocking a number and reporting it as spam. 183 * 184 * <p>This dialog is for the migration of blocked numbers. Its positive action should block a 185 * number, and also marks it as spam if the spam feature is enabled. 186 */ 187 public static class DialogFragmentForBlockingNumberAndReportingAsSpam 188 extends CommonDialogsFragment { 189 190 private boolean isSpamEnabled; 191 newInstance( String displayNumber, boolean isSpamEnabled, OnConfirmListener positiveListener, @Nullable DialogInterface.OnDismissListener dismissListener)192 public static DialogFragment newInstance( 193 String displayNumber, 194 boolean isSpamEnabled, 195 OnConfirmListener positiveListener, 196 @Nullable DialogInterface.OnDismissListener dismissListener) { 197 DialogFragmentForBlockingNumberAndReportingAsSpam fragment = 198 new DialogFragmentForBlockingNumberAndReportingAsSpam(); 199 fragment.displayNumber = displayNumber; 200 fragment.positiveListener = positiveListener; 201 fragment.dismissListener = dismissListener; 202 fragment.isSpamEnabled = isSpamEnabled; 203 return fragment; 204 } 205 206 @Override onCreateDialog(Bundle savedInstanceState)207 public Dialog onCreateDialog(Bundle savedInstanceState) { 208 super.onCreateDialog(savedInstanceState); 209 // Return the newly created dialog 210 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 211 Dialog dialog = 212 alertDialogBuilder 213 .setTitle(getString(R.string.block_number_confirmation_title, displayNumber)) 214 .setMessage( 215 isSpamEnabled 216 ? getString( 217 R.string.block_number_alert_details, getBlockMessage(getContext())) 218 : getString(R.string.block_report_number_alert_details)) 219 .setPositiveButton( 220 R.string.block_number_ok, createGenericOnClickListener(this, positiveListener)) 221 .create(); 222 dialog.setCanceledOnTouchOutside(true); 223 return dialog; 224 } 225 } 226 227 /** 228 * Dialog for blocking a number. 229 * 230 * <p>This dialog is for a spam number that hasn't been blocked. For example, if the user receives 231 * a spam call, this dialog will be shown if they would like to block the number. 232 */ 233 public static class DialogFragmentForBlockingNumber extends CommonDialogsFragment { 234 newInstance( String displayNumber, OnConfirmListener positiveListener, @Nullable DialogInterface.OnDismissListener dismissListener)235 public static DialogFragment newInstance( 236 String displayNumber, 237 OnConfirmListener positiveListener, 238 @Nullable DialogInterface.OnDismissListener dismissListener) { 239 DialogFragmentForBlockingNumberAndReportingAsSpam fragment = 240 new DialogFragmentForBlockingNumberAndReportingAsSpam(); 241 fragment.displayNumber = displayNumber; 242 fragment.positiveListener = positiveListener; 243 fragment.dismissListener = dismissListener; 244 return fragment; 245 } 246 247 @Override onCreateDialog(Bundle savedInstanceState)248 public Dialog onCreateDialog(Bundle savedInstanceState) { 249 super.onCreateDialog(savedInstanceState); 250 // Return the newly created dialog 251 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 252 Dialog dialog = 253 alertDialogBuilder 254 .setTitle(getString(R.string.block_number_confirmation_title, displayNumber)) 255 .setMessage(getString(R.string.block_report_number_alert_details)) 256 .setPositiveButton( 257 R.string.block_number_ok, createGenericOnClickListener(this, positiveListener)) 258 .create(); 259 dialog.setCanceledOnTouchOutside(true); 260 return dialog; 261 } 262 } 263 264 /** 265 * Dialog for unblocking a number and marking it as not spam. 266 * 267 * <p>This dialog is used in the old call log, where unblocking a number will also mark it as not 268 * spam. 269 */ 270 public static class DialogFragmentForUnblockingNumberAndReportingAsNotSpam 271 extends CommonDialogsFragment { 272 273 /** Whether or not the number is spam. */ 274 private boolean isSpam; 275 newInstance( String displayNumber, boolean isSpam, OnConfirmListener positiveListener, @Nullable DialogInterface.OnDismissListener dismissListener)276 public static DialogFragment newInstance( 277 String displayNumber, 278 boolean isSpam, 279 OnConfirmListener positiveListener, 280 @Nullable DialogInterface.OnDismissListener dismissListener) { 281 DialogFragmentForUnblockingNumberAndReportingAsNotSpam fragment = 282 new DialogFragmentForUnblockingNumberAndReportingAsNotSpam(); 283 fragment.displayNumber = displayNumber; 284 fragment.isSpam = isSpam; 285 fragment.positiveListener = positiveListener; 286 fragment.dismissListener = dismissListener; 287 return fragment; 288 } 289 290 @Override onCreateDialog(Bundle savedInstanceState)291 public Dialog onCreateDialog(Bundle savedInstanceState) { 292 super.onCreateDialog(savedInstanceState); 293 // Return the newly created dialog 294 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 295 if (isSpam) { 296 alertDialogBuilder 297 .setMessage(R.string.unblock_number_alert_details) 298 .setTitle(getString(R.string.unblock_report_number_alert_title, displayNumber)); 299 } else { 300 alertDialogBuilder.setMessage( 301 getString(R.string.unblock_report_number_alert_title, displayNumber)); 302 } 303 Dialog dialog = 304 alertDialogBuilder 305 .setPositiveButton( 306 R.string.unblock_number_ok, createGenericOnClickListener(this, positiveListener)) 307 .create(); 308 dialog.setCanceledOnTouchOutside(true); 309 return dialog; 310 } 311 } 312 313 /** 314 * Dialog for unblocking a number. 315 * 316 * <p>This dialog is used in the new call log, where unblocking a number will *not* mark it as not 317 * spam. 318 */ 319 public static class DialogFragmentForUnblockingNumber extends CommonDialogsFragment { 320 newInstance( String displayNumber, OnConfirmListener positiveListener, @Nullable DialogInterface.OnDismissListener dismissListener)321 public static DialogFragment newInstance( 322 String displayNumber, 323 OnConfirmListener positiveListener, 324 @Nullable DialogInterface.OnDismissListener dismissListener) { 325 DialogFragmentForUnblockingNumberAndReportingAsNotSpam fragment = 326 new DialogFragmentForUnblockingNumberAndReportingAsNotSpam(); 327 fragment.displayNumber = displayNumber; 328 fragment.positiveListener = positiveListener; 329 fragment.dismissListener = dismissListener; 330 return fragment; 331 } 332 333 @Override onCreateDialog(Bundle savedInstanceState)334 public Dialog onCreateDialog(Bundle savedInstanceState) { 335 super.onCreateDialog(savedInstanceState); 336 // Return the newly created dialog 337 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 338 alertDialogBuilder.setMessage( 339 getString(R.string.unblock_report_number_alert_title, displayNumber)); 340 Dialog dialog = 341 alertDialogBuilder 342 .setPositiveButton( 343 R.string.unblock_number_ok, createGenericOnClickListener(this, positiveListener)) 344 .create(); 345 dialog.setCanceledOnTouchOutside(true); 346 return dialog; 347 } 348 } 349 350 /** Dialog for reporting a number as not spam. */ 351 public static class DialogFragmentForReportingNotSpam extends CommonDialogsFragment { 352 newInstance( String displayNumber, OnConfirmListener positiveListener, @Nullable DialogInterface.OnDismissListener dismissListener)353 public static DialogFragment newInstance( 354 String displayNumber, 355 OnConfirmListener positiveListener, 356 @Nullable DialogInterface.OnDismissListener dismissListener) { 357 DialogFragmentForReportingNotSpam fragment = new DialogFragmentForReportingNotSpam(); 358 fragment.displayNumber = displayNumber; 359 fragment.positiveListener = positiveListener; 360 fragment.dismissListener = dismissListener; 361 return fragment; 362 } 363 364 @Override onCreateDialog(Bundle savedInstanceState)365 public Dialog onCreateDialog(Bundle savedInstanceState) { 366 super.onCreateDialog(savedInstanceState); 367 // Return the newly created dialog 368 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 369 Dialog dialog = 370 alertDialogBuilder 371 .setTitle(R.string.report_not_spam_alert_title) 372 .setMessage(getString(R.string.report_not_spam_alert_details, displayNumber)) 373 .setPositiveButton( 374 R.string.report_not_spam_alert_button, 375 createGenericOnClickListener(this, positiveListener)) 376 .create(); 377 dialog.setCanceledOnTouchOutside(true); 378 return dialog; 379 } 380 } 381 } 382