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.AlertDialog; 21 import android.app.Dialog; 22 import android.app.DialogFragment; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.os.Bundle; 26 import android.support.annotation.Nullable; 27 import android.view.View; 28 import android.widget.CheckBox; 29 import android.widget.TextView; 30 import com.android.dialer.blocking.FilteredNumberCompat; 31 32 /** 33 * Helper class for creating dialog fragments to block a number and/or report it as spam/not spam. 34 */ 35 public final class BlockReportSpamDialogs { 36 37 public static final String BLOCK_REPORT_SPAM_DIALOG_TAG = "BlockReportSpamDialog"; 38 public static final String BLOCK_DIALOG_TAG = "BlockDialog"; 39 public static final String UNBLOCK_DIALOG_TAG = "UnblockDialog"; 40 public static final String NOT_SPAM_DIALOG_TAG = "NotSpamDialog"; 41 42 /** Creates a dialog with the default cancel button listener (dismisses dialog). */ 43 private static AlertDialog.Builder createDialogBuilder( 44 Activity activity, final DialogFragment fragment) { 45 return new AlertDialog.Builder(activity, R.style.AlertDialogTheme) 46 .setCancelable(true) 47 .setNegativeButton(android.R.string.cancel, (dialog, which) -> fragment.dismiss()); 48 } 49 50 /** 51 * Creates a generic click listener which dismisses the fragment and then calls the actual 52 * listener. 53 */ 54 private static DialogInterface.OnClickListener createGenericOnClickListener( 55 final DialogFragment fragment, final OnConfirmListener listener) { 56 return (dialog, which) -> { 57 fragment.dismiss(); 58 listener.onClick(); 59 }; 60 } 61 62 private static String getBlockMessage(Context context) { 63 String message; 64 if (FilteredNumberCompat.useNewFiltering(context)) { 65 message = context.getString(R.string.block_number_confirmation_message_new_filtering); 66 } else { 67 message = context.getString(R.string.block_report_number_alert_details); 68 } 69 return message; 70 } 71 72 /** 73 * Listener passed to block/report spam dialog for positive click in {@link 74 * BlockReportSpamDialogFragment}. 75 */ 76 public interface OnSpamDialogClickListener { 77 78 /** 79 * Called when user clicks on positive button in block/report spam dialog. 80 * 81 * @param isSpamChecked Whether the spam checkbox is checked. 82 */ 83 void onClick(boolean isSpamChecked); 84 } 85 86 /** Listener passed to all dialogs except the block/report spam dialog for positive click. */ 87 public interface OnConfirmListener { 88 89 /** Called when user clicks on positive button in the dialog. */ 90 void onClick(); 91 } 92 93 /** Contains the common attributes between all block/unblock/report spam dialog fragments. */ 94 private abstract static class CommonDialogsFragment extends DialogFragment { 95 96 /** The number to display in the dialog title. */ 97 protected String displayNumber; 98 99 /** Called when dialog positive button is pressed. */ 100 protected OnConfirmListener positiveListener; 101 102 /** Called when dialog is dismissed. */ 103 @Nullable protected DialogInterface.OnDismissListener dismissListener; 104 105 @Override 106 public void onDismiss(DialogInterface dialog) { 107 if (dismissListener != null) { 108 dismissListener.onDismiss(dialog); 109 } 110 super.onDismiss(dialog); 111 } 112 113 @Override 114 public void onPause() { 115 // The dialog is dismissed onPause, i.e. rotation. 116 dismiss(); 117 dismissListener = null; 118 positiveListener = null; 119 displayNumber = null; 120 super.onPause(); 121 } 122 } 123 124 /** Dialog for block/report spam with the mark as spam checkbox. */ 125 public static class BlockReportSpamDialogFragment extends CommonDialogsFragment { 126 127 /** Called when dialog positive button is pressed. */ 128 private OnSpamDialogClickListener onSpamDialogClickListener; 129 130 /** Whether the mark as spam checkbox is checked before displaying the dialog. */ 131 private boolean spamChecked; 132 133 public static DialogFragment newInstance( 134 String displayNumber, 135 boolean spamChecked, 136 OnSpamDialogClickListener onSpamDialogClickListener, 137 @Nullable DialogInterface.OnDismissListener dismissListener) { 138 BlockReportSpamDialogFragment fragment = new BlockReportSpamDialogFragment(); 139 fragment.spamChecked = spamChecked; 140 fragment.displayNumber = displayNumber; 141 fragment.onSpamDialogClickListener = onSpamDialogClickListener; 142 fragment.dismissListener = dismissListener; 143 return fragment; 144 } 145 146 @Override 147 public Dialog onCreateDialog(Bundle savedInstanceState) { 148 super.onCreateDialog(savedInstanceState); 149 View dialogView = View.inflate(getActivity(), R.layout.block_report_spam_dialog, null); 150 final CheckBox isSpamCheckbox = 151 (CheckBox) dialogView.findViewById(R.id.report_number_as_spam_action); 152 // Listen for changes on the checkbox and update if orientation changes 153 isSpamCheckbox.setChecked(spamChecked); 154 isSpamCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> spamChecked = isChecked); 155 156 TextView details = (TextView) dialogView.findViewById(R.id.block_details); 157 details.setText(getBlockMessage(getContext())); 158 159 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 160 Dialog blockReportSpamDialog = 161 alertDialogBuilder 162 .setView(dialogView) 163 .setTitle(getString(R.string.block_report_number_alert_title, displayNumber)) 164 .setPositiveButton( 165 R.string.block_number_ok, 166 (dialog, which) -> { 167 dismiss(); 168 onSpamDialogClickListener.onClick(isSpamCheckbox.isChecked()); 169 }) 170 .create(); 171 blockReportSpamDialog.setCanceledOnTouchOutside(true); 172 return blockReportSpamDialog; 173 } 174 } 175 176 /** Dialog for blocking a number. */ 177 public static class BlockDialogFragment extends CommonDialogsFragment { 178 179 private boolean isSpamEnabled; 180 181 public static DialogFragment newInstance( 182 String displayNumber, 183 boolean isSpamEnabled, 184 OnConfirmListener positiveListener, 185 @Nullable DialogInterface.OnDismissListener dismissListener) { 186 BlockDialogFragment fragment = new BlockDialogFragment(); 187 fragment.displayNumber = displayNumber; 188 fragment.positiveListener = positiveListener; 189 fragment.dismissListener = dismissListener; 190 fragment.isSpamEnabled = isSpamEnabled; 191 return fragment; 192 } 193 194 @Override 195 public Dialog onCreateDialog(Bundle savedInstanceState) { 196 super.onCreateDialog(savedInstanceState); 197 // Return the newly created dialog 198 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 199 Dialog dialog = 200 alertDialogBuilder 201 .setTitle(getString(R.string.block_number_confirmation_title, displayNumber)) 202 .setMessage( 203 isSpamEnabled 204 ? getString( 205 R.string.block_number_alert_details, getBlockMessage(getContext())) 206 : getString(R.string.block_report_number_alert_details)) 207 .setPositiveButton( 208 R.string.block_number_ok, createGenericOnClickListener(this, positiveListener)) 209 .create(); 210 dialog.setCanceledOnTouchOutside(true); 211 return dialog; 212 } 213 } 214 215 /** Dialog for unblocking a number. */ 216 public static class UnblockDialogFragment extends CommonDialogsFragment { 217 218 /** Whether or not the number is spam. */ 219 private boolean isSpam; 220 221 public static DialogFragment newInstance( 222 String displayNumber, 223 boolean isSpam, 224 OnConfirmListener positiveListener, 225 @Nullable DialogInterface.OnDismissListener dismissListener) { 226 UnblockDialogFragment fragment = new UnblockDialogFragment(); 227 fragment.displayNumber = displayNumber; 228 fragment.isSpam = isSpam; 229 fragment.positiveListener = positiveListener; 230 fragment.dismissListener = dismissListener; 231 return fragment; 232 } 233 234 @Override 235 public Dialog onCreateDialog(Bundle savedInstanceState) { 236 super.onCreateDialog(savedInstanceState); 237 // Return the newly created dialog 238 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 239 if (isSpam) { 240 alertDialogBuilder 241 .setMessage(R.string.unblock_number_alert_details) 242 .setTitle(getString(R.string.unblock_report_number_alert_title, displayNumber)); 243 } else { 244 alertDialogBuilder.setMessage( 245 getString(R.string.unblock_report_number_alert_title, displayNumber)); 246 } 247 Dialog dialog = 248 alertDialogBuilder 249 .setPositiveButton( 250 R.string.unblock_number_ok, createGenericOnClickListener(this, positiveListener)) 251 .create(); 252 dialog.setCanceledOnTouchOutside(true); 253 return dialog; 254 } 255 } 256 257 /** Dialog for reporting a number as not spam. */ 258 public static class ReportNotSpamDialogFragment extends CommonDialogsFragment { 259 260 public static DialogFragment newInstance( 261 String displayNumber, 262 OnConfirmListener positiveListener, 263 @Nullable DialogInterface.OnDismissListener dismissListener) { 264 ReportNotSpamDialogFragment fragment = new ReportNotSpamDialogFragment(); 265 fragment.displayNumber = displayNumber; 266 fragment.positiveListener = positiveListener; 267 fragment.dismissListener = dismissListener; 268 return fragment; 269 } 270 271 @Override 272 public Dialog onCreateDialog(Bundle savedInstanceState) { 273 super.onCreateDialog(savedInstanceState); 274 // Return the newly created dialog 275 AlertDialog.Builder alertDialogBuilder = createDialogBuilder(getActivity(), this); 276 Dialog dialog = 277 alertDialogBuilder 278 .setTitle(R.string.report_not_spam_alert_title) 279 .setMessage(getString(R.string.report_not_spam_alert_details, displayNumber)) 280 .setPositiveButton( 281 R.string.report_not_spam_alert_button, 282 createGenericOnClickListener(this, positiveListener)) 283 .create(); 284 dialog.setCanceledOnTouchOutside(true); 285 return dialog; 286 } 287 } 288 } 289