diff options
-rw-r--r-- | res/values/ids.xml | 1 | ||||
-rw-r--r-- | res/values/strings.xml | 32 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogAdapter.java | 104 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogListItemHelper.java | 3 | ||||
-rw-r--r-- | src/com/android/dialer/calllog/CallLogListItemViewHolder.java | 118 | ||||
-rw-r--r-- | src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java | 95 | ||||
-rw-r--r-- | src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java | 154 |
7 files changed, 376 insertions, 131 deletions
diff --git a/res/values/ids.xml b/res/values/ids.xml index cb2025aa9..0034fe3d4 100644 --- a/res/values/ids.xml +++ b/res/values/ids.xml @@ -18,5 +18,6 @@ <item type="id" name="context_menu_copy_to_clipboard" /> <item type="id" name="context_menu_copy_transcript_to_clipboard" /> <item type="id" name="context_menu_edit_before_call" /> + <item type="id" name="context_menu_block_number" /> <item type="id" name="settings_header_sounds_and_vibration" /> </resources> diff --git a/res/values/strings.xml b/res/values/strings.xml index 1ce6ab65c..7bd88baef 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -52,6 +52,24 @@ <!-- Option displayed in context menu to copy long pressed voicemail transcription to clipboard [CHAR LIMIT=64] --> <string name="copy_transcript_text">Copy transcription to clipboard</string> + <!-- Menu item used to block a number from the call log [CHAR LIMIT=64] --> + <string name="call_log_block_number">Block number</string> + + <!-- Text for snackbar to undo blocking a number. [CHAR LIMIT=64] --> + <string name="snackbar_number_blocked"> + <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g> added to block list</string> + + <!-- Menu item used to unblock a number from the call log [CHAR LIMIT=64]--> + <string name="call_log_unblock_number">Unblock number</string> + + <!-- Text for snackbar to undo unblocking a number. [CHAR LIMIT=64] --> + <string name="snackbar_number_unblocked"> + <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g> + removed from block list</string> + + <!-- Text for undo button in snackbar for blocking/unblocking number. [CHAR LIMIT=10] --> + <string name="block_number_undo">UNDO</string> + <!-- Menu item used to copy a number from the call log to the dialer so it can be edited before calling it --> <string name="call_log_edit_number_before_call">Edit number before call</string> @@ -490,6 +508,20 @@ [CHAR LIMIT=30] --> <string name="call_log_voicemail_title">Voicemail</string> + <!-- Confirmation dialog for blocking a number. [CHAR LIMIT=NONE] --> + <string name="blockNumberConfirmation">Add + <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g> to your block list?</string> + + <!-- Block number alert dialog button [CHAR LIMIT=32] --> + <string name="blockNumberOk">Block number</string> + + <!-- Confirmation dialog for unblocking a number. [CHAR LIMIT=NONE] --> + <string name="unblockNumberConfirmation">Remove + <xliff:g id="number" example="(555) 555-5555">%1$s</xliff:g> from your block list?</string> + + <!-- Unblock number alert dialog button [CHAR LIMIT=32] --> + <string name="unblockNumberOk">Unblock number</string> + <!-- Accessibility text for the tab showing recent and favorite contacts who can be called. [CHAR LIMIT=40] --> <string name="tab_speed_dial">Speed dial</string> diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java index 4593e5e4d..4d4d454d0 100644 --- a/src/com/android/dialer/calllog/CallLogAdapter.java +++ b/src/com/android/dialer/calllog/CallLogAdapter.java @@ -22,12 +22,10 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; -import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.v7.widget.RecyclerView; import android.os.Bundle; import android.os.Trace; -import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.provider.CallLog; import android.support.v7.widget.RecyclerView.ViewHolder; @@ -35,28 +33,18 @@ import android.telecom.PhoneAccountHandle; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.Log; -import android.view.ContextMenu; import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.MenuItem.OnMenuItemClickListener; import android.view.View; import android.view.View.AccessibilityDelegate; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.ContextMenu.ContextMenuInfo; import android.view.accessibility.AccessibilityEvent; -import android.widget.TextView; -import com.android.contacts.common.CallUtil; -import com.android.contacts.common.ClipboardUtils; import com.android.contacts.common.util.PermissionsUtil; -import com.android.dialer.DialtactsActivity; import com.android.dialer.PhoneCallDetails; import com.android.dialer.R; import com.android.dialer.contactinfo.ContactInfoCache; import com.android.dialer.contactinfo.ContactInfoCache.OnContactInfoChangedListener; -import com.android.dialer.util.DialerUtils; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler; import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; @@ -96,6 +84,7 @@ public class CallLogAdapter extends GroupingListAdapter private final ContactInfoHelper mContactInfoHelper; protected final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; private final CallFetcher mCallFetcher; + private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; protected ContactInfoCache mContactInfoCache; @@ -195,89 +184,6 @@ public class CallLogAdapter extends GroupingListAdapter } }; - /** - * Listener that is triggered to populate the context menu with actions to perform on the call's - * number, when the call log entry is long pressed. - */ - private final View.OnCreateContextMenuListener mOnCreateContextMenuListener = - new View.OnCreateContextMenuListener() { - @Override - public void onCreateContextMenu( - ContextMenu menu, View v, ContextMenuInfo menuInfo) { - final CallLogListItemViewHolder vh = (CallLogListItemViewHolder) v.getTag(); - if (TextUtils.isEmpty(vh.number)) { - return; - } - - if (vh.callType == CallLog.Calls.VOICEMAIL_TYPE) { - menu.setHeaderTitle(mContext.getResources().getText(R.string.voicemail)); - } else { - menu.setHeaderTitle(vh.number); - } - - final MenuItem copyItem = menu.add( - ContextMenu.NONE, - R.id.context_menu_copy_to_clipboard, - ContextMenu.NONE, - R.string.copy_number_text); - - copyItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - ClipboardUtils.copyText(mContext, null, vh.number, true); - return true; - } - }); - - // The edit number before call does not show up if any of the conditions apply: - // 1) Number cannot be called - // 2) Number is the voicemail number - // 3) Number is a SIP address - - if (PhoneNumberUtil.canPlaceCallsTo(vh.number, vh.numberPresentation) - && !mTelecomCallLogCache.isVoicemailNumber(vh.accountHandle, vh.number) - && !PhoneNumberUtil.isSipNumber(vh.number)) { - final MenuItem editItem = menu.add( - ContextMenu.NONE, - R.id.context_menu_edit_before_call, - ContextMenu.NONE, - R.string.call_log_edit_number_before_call); - - editItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - final Intent intent = new Intent( - Intent.ACTION_DIAL, CallUtil.getCallUri(vh.number)); - intent.setClass(mContext, DialtactsActivity.class); - DialerUtils.startActivityWithErrorToast(mContext, intent); - return true; - } - }); - } - - final TextView transcriptView = - vh.phoneCallDetailsViews.voicemailTranscriptionView; - if (vh.callType == CallLog.Calls.VOICEMAIL_TYPE - && transcriptView.length() > 0) { - final MenuItem copyTranscriptItem = menu.add( - ContextMenu.NONE, - R.id.context_menu_copy_transcript_to_clipboard, - ContextMenu.NONE, - R.string.copy_transcript_text); - - copyTranscriptItem.setOnMenuItemClickListener( - new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - ClipboardUtils.copyText( - mContext, null, transcriptView.getText(), true); - return true; - } - }); - } - } - }; - private void expandViewHolderActions(CallLogListItemViewHolder viewHolder) { // If another item is expanded, notify it that it has changed. Its actions will be // hidden when it is re-binded because we change mCurrentlyExpandedPosition below. @@ -351,6 +257,8 @@ public class CallLogAdapter extends GroupingListAdapter mCallLogGroupBuilder = new CallLogGroupBuilder(this); mPrefs = PreferenceManager.getDefaultSharedPreferences(context); maybeShowVoicemailPromoCard(); + mFilteredNumberAsyncQueryHandler = + new FilteredNumberAsyncQueryHandler(mContext.getContentResolver()); } public void onSaveInstanceState(Bundle outState) { @@ -439,12 +347,12 @@ public class CallLogAdapter extends GroupingListAdapter mExpandCollapseListener, mTelecomCallLogCache, mCallLogListItemHelper, - mVoicemailPlaybackPresenter); + mVoicemailPlaybackPresenter, + mFilteredNumberAsyncQueryHandler); viewHolder.callLogEntryView.setTag(viewHolder); viewHolder.callLogEntryView.setAccessibilityDelegate(mAccessibilityDelegate); - viewHolder.primaryActionView.setOnCreateContextMenuListener(mOnCreateContextMenuListener); viewHolder.primaryActionView.setTag(viewHolder); return viewHolder; diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java index 1c8e397e4..d18e274ba 100644 --- a/src/com/android/dialer/calllog/CallLogListItemHelper.java +++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java @@ -74,6 +74,9 @@ import com.android.dialer.R; // Cache name or number of caller. Used when setting the content descriptions of buttons // when the actions ViewStub is inflated. views.nameOrNumber = getNameOrNumber(details); + + // Cache country iso. Used for number filtering. + views.countryIso = details.countryIso; } /** diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java index d85deb36f..521b2a429 100644 --- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java +++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java @@ -21,12 +21,15 @@ import android.content.Context; import android.content.res.Resources; import android.content.Intent; import android.net.Uri; +import android.provider.CallLog; import android.provider.CallLog.Calls; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.telecom.PhoneAccountHandle; import android.text.TextUtils; +import android.view.ContextMenu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; @@ -34,12 +37,17 @@ import android.widget.QuickContactBadge; import android.widget.ImageView; import android.widget.TextView; +import com.android.contacts.common.CallUtil; +import com.android.contacts.common.ClipboardUtils; import com.android.contacts.common.ContactPhotoManager; import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest; import com.android.contacts.common.dialog.CallSubjectDialog; import com.android.contacts.common.testing.NeededForTesting; import com.android.contacts.common.util.UriUtils; +import com.android.dialer.DialtactsActivity; import com.android.dialer.R; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler; +import com.android.dialer.filterednumber.FilterNumberDialogFragment; import com.android.dialer.util.DialerUtils; import com.android.dialer.util.PhoneNumberUtil; import com.android.dialer.voicemail.VoicemailPlaybackPresenter; @@ -52,7 +60,8 @@ import com.android.dialer.voicemail.VoicemailPlaybackLayout; * This object also contains UI logic pertaining to the view, to isolate it from the CallLogAdapter. */ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder - implements View.OnClickListener { + implements View.OnClickListener, MenuItem.OnMenuItemClickListener, + View.OnCreateContextMenuListener { /** The root view of the call log list item */ public final View rootView; @@ -116,12 +125,24 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder public String numberType; /** + * The country iso for the call. Cached here as the call back + * intent is set only when the actions ViewStub is inflated. + */ + public String countryIso; + + /** * The type of call for the current call log entry. Cached here as the call back * intent is set only when the actions ViewStub is inflated. */ public int callType; /** + * ID for blocked numbers database. + * Set when context menu is created, if the number is blocked. + */ + public Integer blockId; + + /** * The account for the current call log entry. Cached here as the call back * intent is set only when the actions ViewStub is inflated. */ @@ -156,6 +177,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder private final TelecomCallLogCache mTelecomCallLogCache; private final CallLogListItemHelper mCallLogListItemHelper; private final VoicemailPlaybackPresenter mVoicemailPlaybackPresenter; + private final FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; private final int mPhotoSize; @@ -168,6 +190,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, VoicemailPlaybackPresenter voicemailPlaybackPresenter, + FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler, View rootView, QuickContactBadge quickContactView, View primaryActionView, @@ -182,6 +205,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder mTelecomCallLogCache = telecomCallLogCache; mCallLogListItemHelper = callLogListItemHelper; mVoicemailPlaybackPresenter = voicemailPlaybackPresenter; + mFilteredNumberAsyncQueryHandler = filteredNumberAsyncQueryHandler; this.rootView = rootView; this.quickContactView = quickContactView; @@ -202,6 +226,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder primaryActionButtonView.setOnClickListener(this); primaryActionView.setOnClickListener(mExpandCollapseListener); + primaryActionView.setOnCreateContextMenuListener(this); } public static CallLogListItemViewHolder create( @@ -210,7 +235,8 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder View.OnClickListener expandCollapseListener, TelecomCallLogCache telecomCallLogCache, CallLogListItemHelper callLogListItemHelper, - VoicemailPlaybackPresenter voicemailPlaybackPresenter) { + VoicemailPlaybackPresenter voicemailPlaybackPresenter, + FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { return new CallLogListItemViewHolder( context, @@ -218,6 +244,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder telecomCallLogCache, callLogListItemHelper, voicemailPlaybackPresenter, + filteredNumberAsyncQueryHandler, view, (QuickContactBadge) view.findViewById(R.id.quick_contact_photo), view.findViewById(R.id.primary_action_view), @@ -227,6 +254,92 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder (ImageView) view.findViewById(R.id.primary_action_button)); } + @Override + public void onCreateContextMenu( + final ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + if (TextUtils.isEmpty(number)) { + return; + } + + if (callType == CallLog.Calls.VOICEMAIL_TYPE) { + menu.setHeaderTitle(mContext.getResources().getText(R.string.voicemail)); + } else { + menu.setHeaderTitle(number); + } + + menu.add(ContextMenu.NONE, R.id.context_menu_copy_to_clipboard, ContextMenu.NONE, + R.string.copy_number_text) + .setOnMenuItemClickListener(this); + + // The edit number before call does not show up if any of the conditions apply: + // 1) Number cannot be called + // 2) Number is the voicemail number + // 3) Number is a SIP address + + if (PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) + && !mTelecomCallLogCache.isVoicemailNumber(accountHandle, number) + && !PhoneNumberUtil.isSipNumber(number)) { + menu.add(ContextMenu.NONE, R.id.context_menu_edit_before_call, ContextMenu.NONE, + R.string.call_log_edit_number_before_call) + .setOnMenuItemClickListener(this); + } + + if (callType == CallLog.Calls.VOICEMAIL_TYPE + && phoneCallDetailsViews.voicemailTranscriptionView.length() > 0) { + menu.add(ContextMenu.NONE, R.id.context_menu_copy_transcript_to_clipboard, + ContextMenu.NONE, R.string.copy_transcript_text) + .setOnMenuItemClickListener(this); + } + + try { + mFilteredNumberAsyncQueryHandler.isBlocked( + new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() { + @Override + public void onCheckComplete(Integer id) { + blockId = id; + int blockTitleId = blockId == null ? R.string.call_log_block_number + : R.string.call_log_unblock_number; + final MenuItem blockItem = menu.add( + ContextMenu.NONE, + R.id.context_menu_block_number, + ContextMenu.NONE, + blockTitleId); + blockItem.setOnMenuItemClickListener( + CallLogListItemViewHolder.this); + } + }, info.normalizedNumber, number, countryIso); + } catch (IllegalArgumentException e) { + } + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + switch (item.getItemId()) { + case R.id.context_menu_block_number: + FilterNumberDialogFragment newFragment = + FilterNumberDialogFragment.newInstance(blockId, info.normalizedNumber, + number, countryIso, info.formattedNumber); + newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler); + newFragment.show(((Activity) mContext).getFragmentManager(), + FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT); + return true; + case R.id.context_menu_copy_to_clipboard: + ClipboardUtils.copyText(mContext, null, number, true); + return true; + case R.id.context_menu_copy_transcript_to_clipboard: + ClipboardUtils.copyText(mContext, null, + phoneCallDetailsViews.voicemailTranscriptionView.getText(), true); + return true; + case R.id.context_menu_edit_before_call: + final Intent intent = new Intent( + Intent.ACTION_DIAL, CallUtil.getCallUri(number)); + intent.setClass(mContext, DialtactsActivity.class); + DialerUtils.startActivityWithErrorToast(mContext, intent); + return true; + } + return false; + } + /** * Configures the action buttons in the expandable actions ViewStub. The ViewStub is not * inflated during initial binding, so click handlers, tags and accessibility text must be set @@ -488,6 +601,7 @@ public final class CallLogListItemViewHolder extends RecyclerView.ViewHolder telecomCallLogCache, new CallLogListItemHelper(phoneCallDetailsHelper, resources, telecomCallLogCache), null /* voicemailPlaybackPresenter */, + null /* filteredNumberAsyncQueryHandler */, new View(context), new QuickContactBadge(context), new View(context), diff --git a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java index 58a717b8b..2fdea0d13 100644 --- a/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java +++ b/src/com/android/dialer/database/FilteredNumberAsyncQueryHandler.java @@ -21,6 +21,8 @@ import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabaseCorruptException; import android.net.Uri; import android.telephony.PhoneNumberUtils; @@ -51,15 +53,28 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { } public interface OnCheckBlockedListener { - public void onQueryComplete(Integer id); + /** + * Invoked after querying if a number is blocked. + * @param id The ID of the row if blocked, null otherwise. + */ + public void onCheckComplete(Integer id); } public interface OnBlockNumberListener { - public void onInsertComplete(Uri uri); + /** + * Invoked after inserting a blocked number. + * @param uri The uri of the newly created row. + */ + public void onBlockComplete(Uri uri); } public interface OnUnblockNumberListener { - public void onDeleteComplete(int rows); + /** + * Invoked after removing a blocked number + * @param rows The number of rows affected (expected value 1). + * @param values The deleted data (used for restoration). + */ + public void onUnblockComplete(int rows, ContentValues values); } @Override @@ -93,7 +108,6 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { /** * Check if the number + country iso given has been blocked. * This method normalizes the number for the lookup if normalizedNumber is null. - * Returns to the listener the the ID of the row if blocked, null otherwise. */ public final void isBlocked(final OnCheckBlockedListener listener, String normalizedNumber, String number, String countryIso) { @@ -108,25 +122,24 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { /** * Check if the normalized number given has been blocked. - * Returns to the listener the ID of the row if blocked, null otherwise. */ public final void isBlocked(final OnCheckBlockedListener listener, - String normalizedNumber) { + String normalizedNumber) { startQuery(NO_TOKEN, new Listener() { @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { if (cursor.getCount() != 1) { - listener.onQueryComplete(null); + listener.onCheckComplete(null); return; } cursor.moveToFirst(); if (cursor.getInt(cursor.getColumnIndex(FilteredNumberColumns.TYPE)) != FilteredNumberTypes.BLOCKED_NUMBER) { - listener.onQueryComplete(null); + listener.onCheckComplete(null); return; } - listener.onQueryComplete( + listener.onCheckComplete( cursor.getInt(cursor.getColumnIndex(FilteredNumberColumns._ID))); } }, @@ -139,22 +152,11 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { /** * Add a number manually blocked by the user. - * Returns to the listener the URL of the newly created row. */ public final void blockNumber(final OnBlockNumberListener listener, - String number, String countryIso) { - blockNumber(listener, - PhoneNumberUtils.formatNumberToE164(number, countryIso), number, countryIso); - } - - /** - * Add a number manually blocked by the user. - * Returns to the listener the URL of the newly created row. - */ - public final void blockNumber(final OnBlockNumberListener listener, - String normalizedNumber, String number, String countryIso) { + String normalizedNumber, String number, String countryIso) { if (normalizedNumber == null) { - blockNumber(listener, number, countryIso); + normalizedNumber = PhoneNumberUtils.formatNumberToE164(number, countryIso); } ContentValues v = new ContentValues(); v.put(FilteredNumberColumns.NORMALIZED_NUMBER, normalizedNumber); @@ -162,30 +164,61 @@ public class FilteredNumberAsyncQueryHandler extends AsyncQueryHandler { v.put(FilteredNumberColumns.COUNTRY_ISO, countryIso); v.put(FilteredNumberColumns.TYPE, FilteredNumberTypes.BLOCKED_NUMBER); v.put(FilteredNumberColumns.SOURCE, FilteredNumberSources.USER); + blockNumber(listener, v); + } + + /** + * Block a number with specified ContentValues. Can be manually added or a restored row + * from performing the 'undo' action after unblocking. + */ + public final void blockNumber(final OnBlockNumberListener listener, ContentValues values) { startInsert(NO_TOKEN, new Listener() { @Override public void onInsertComplete(int token, Object cookie, Uri uri) { - listener.onInsertComplete(uri); + listener.onBlockComplete(uri); } - }, getContentUri(null), v); + }, getContentUri(null), values); } /** * Removes row from database. * Caller should call {@link FilteredNumberAsyncQueryHandler#isBlocked} first. - * @param id the ID of the row to remove, from {@link FilteredNumberAsyncQueryHandler#isBlocked}. - * Returns to the listener the number of rows affected. Expected value is 1. + * @param id The ID of row to remove, from {@link FilteredNumberAsyncQueryHandler#isBlocked}. */ public final void unblock(final OnUnblockNumberListener listener, Integer id) { if (id == null) { throw new IllegalArgumentException("Null id passed into unblock"); } - startDelete(NO_TOKEN, new Listener() { + unblock(listener, getContentUri(id)); + } + + /** + * Removes row from database. + * @param uri The uri of row to remove, from + * {@link FilteredNumberAsyncQueryHandler#blockNumber}. + */ + public final void unblock(final OnUnblockNumberListener listener, final Uri uri) { + startQuery(NO_TOKEN, new Listener() { @Override - public void onDeleteComplete(int token, Object cookie, int result) { - listener.onDeleteComplete(result); + public void onQueryComplete(int token, Object cookie, Cursor cursor) { + if (cursor.getCount() != 1) { + throw new SQLiteDatabaseCorruptException + ("Returned " + cursor.getCount() + " rows for uri " + + uri + "where 1 expected."); + } + cursor.moveToFirst(); + final ContentValues values = new ContentValues(); + DatabaseUtils.cursorRowToContentValues(cursor, values); + values.remove(FilteredNumberColumns._ID); + + startDelete(NO_TOKEN, new Listener() { + @Override + public void onDeleteComplete(int token, Object cookie, int result) { + listener.onUnblockComplete(result, values); + } + }, uri, null, null); } - }, getContentUri(id), null, null); + }, uri, null, null, null, null); } -} +}
\ No newline at end of file diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java new file mode 100644 index 000000000..f94d0f842 --- /dev/null +++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2015 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.filterednumber; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.ContentValues; +import android.content.DialogInterface; +import android.net.Uri; +import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.view.View; + +import com.android.dialer.R; +import com.android.dialer.database.FilteredNumberAsyncQueryHandler; + +public class FilterNumberDialogFragment extends DialogFragment { + public static final String BLOCK_DIALOG_FRAGMENT = "blockUnblockNumberDialog"; + + private static final String ARG_BLOCK_ID = "argBlockId"; + private static final String ARG_NORMALIZED_NUMBER = "argNormalizedNumber"; + private static final String ARG_NUMBER = "argNumber"; + private static final String ARG_COUNTRY_ISO = "argCountryIso"; + private static final String ARG_DISPLAY_NUMBER = "argDisplayNumber"; + + private FilteredNumberAsyncQueryHandler mHandler; + + public void setQueryHandler (FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) { + mHandler = filteredNumberAsyncQueryHandler; + } + + public static FilterNumberDialogFragment newInstance(Integer blockId, String normalizedNumber, + String number, String countryIso, String displayNumber) { + final FilterNumberDialogFragment fragment = new FilterNumberDialogFragment(); + final Bundle args = new Bundle(); + if (blockId != null) { + args.putInt(ARG_BLOCK_ID, blockId.intValue()); + } + args.putString(ARG_NORMALIZED_NUMBER, normalizedNumber); + args.putString(ARG_NUMBER, number); + args.putString(ARG_COUNTRY_ISO, countryIso); + args.putString(ARG_DISPLAY_NUMBER, displayNumber); + fragment.setArguments(args); + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + super.onCreateDialog(savedInstanceState); + final boolean isBlocked = getArguments().containsKey(ARG_BLOCK_ID); + final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER); + + String message; + String okText; + if (isBlocked) { + message = getString(R.string.unblockNumberConfirmation, displayNumber); + okText = getString(R.string.unblockNumberOk); + } else { + message = getString(R.string.blockNumberConfirmation, displayNumber); + okText = getString(R.string.blockNumberOk); + } + + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) + .setMessage(message) + .setPositiveButton(okText, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + if (isBlocked) { + unblockNumber(); + } else { + blockNumber(); + } + } + }) + .setNegativeButton(android.R.string.cancel, null); + return builder.create(); + } + + public void blockNumber() { + final View view = getActivity().findViewById(R.id.floating_action_button_container); + final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER); + final String message = getString(R.string.snackbar_number_blocked, displayNumber); + final String undoMessage = getString(R.string.snackbar_number_unblocked, displayNumber); + final FilteredNumberAsyncQueryHandler.OnUnblockNumberListener undoListener = + new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() { + @Override + public void onUnblockComplete(int rows, ContentValues values) { + Snackbar.make(view, undoMessage, Snackbar.LENGTH_LONG).show(); + } + }; + + mHandler.blockNumber( + new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() { + @Override + public void onBlockComplete(final Uri uri) { + Snackbar.make(view, message, Snackbar.LENGTH_LONG) + .setAction(R.string.block_number_undo, + // Delete the newly created row on 'undo'. + new View.OnClickListener() { + @Override + public void onClick(View view) { + mHandler.unblock(undoListener, uri); + } + }) + .show(); + } + }, getArguments().getString(ARG_NORMALIZED_NUMBER), + getArguments().getString(ARG_NUMBER), getArguments().getString(ARG_COUNTRY_ISO)); + } + + public void unblockNumber() { + final View view = getActivity().findViewById(R.id.floating_action_button_container); + final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER); + final String message = getString(R.string.snackbar_number_unblocked, displayNumber); + final String undoMessage = getString(R.string.snackbar_number_blocked, displayNumber); + final FilteredNumberAsyncQueryHandler.OnBlockNumberListener undoListener = + new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() { + @Override + public void onBlockComplete(final Uri uri) { + Snackbar.make(view, undoMessage, Snackbar.LENGTH_LONG).show(); + } + }; + mHandler.unblock( + new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() { + @Override + public void onUnblockComplete(int rows, final ContentValues values) { + Snackbar.make(view, message, Snackbar.LENGTH_LONG) + .setAction(R.string.block_number_undo, + new View.OnClickListener() { + // Re-insert the row on 'undo', with a new ID. + @Override + public void onClick(View view) { + mHandler.blockNumber(undoListener, values); + } + }) + .show(); + } + }, getArguments().getInt(ARG_BLOCK_ID)); + } +}
\ No newline at end of file |