From 5a2b1b2e7cbe8fd5c402ffe0386920b3a63340fa Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Fri, 17 Nov 2017 18:17:53 -0800 Subject: Added place voice call search action to regular search. When a user types a phone number into the search bar, there isn't an intuitive way for them to place a call when the number doesn't match any existing contacts in the new search UI. This change adds the option to place a voice call from regular search, like the old UI. Bug: 69385190 Test: NSFT PiperOrigin-RevId: 176189153 Change-Id: I6c1561bcce104c56855d996570a79b34da7230ff --- .../searchfragment/list/NewSearchFragment.java | 20 ++++++--- .../list/SearchActionViewHolder.java | 37 ++++++++++++--- .../dialer/searchfragment/list/SearchAdapter.java | 10 +++-- .../searchfragment/list/res/values/strings.xml | 5 ++- .../searchfragment/testing/TestCursorSchema.java | 47 ------------------- .../searchfragment/testing/TestSearchCursor.java | 52 ---------------------- 6 files changed, 57 insertions(+), 114 deletions(-) delete mode 100644 java/com/android/dialer/searchfragment/testing/TestCursorSchema.java delete mode 100644 java/com/android/dialer/searchfragment/testing/TestSearchCursor.java (limited to 'java/com/android/dialer/searchfragment') diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java index 93263ceb2..df2714690 100644 --- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java +++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java @@ -142,7 +142,7 @@ public final class NewSearchFragment extends Fragment LayoutInflater inflater, @Nullable ViewGroup parent, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_search, parent, false); adapter = new SearchAdapter(getContext(), new SearchCursorManager(), this); - adapter.setQuery(query, rawNumber); + adapter.setQuery(query, rawNumber, callInitiationType); adapter.setSearchActions(getActions()); adapter.setZeroSuggestVisible(getArguments().getBoolean(KEY_SHOW_ZERO_SUGGEST)); emptyContentView = view.findViewById(R.id.empty_view); @@ -260,7 +260,7 @@ public final class NewSearchFragment extends Fragment this.query = query; this.callInitiationType = callInitiationType; if (adapter != null) { - adapter.setQuery(query, rawNumber); + adapter.setQuery(query, rawNumber, callInitiationType); adapter.setSearchActions(getActions()); adapter.setZeroSuggestVisible(isRegularSearch()); loadNearbyPlacesCursor(); @@ -445,19 +445,27 @@ public final class NewSearchFragment extends Fragment * the list of supported actions, see {@link SearchActionViewHolder.Action}. */ private List getActions() { - boolean nonDialableQueryInRegularSearch = - isRegularSearch() && !PhoneNumberUtils.isGlobalPhoneNumber(query); + boolean isDialableNumber = PhoneNumberUtils.isGlobalPhoneNumber(query); + boolean nonDialableQueryInRegularSearch = isRegularSearch() && !isDialableNumber; if (TextUtils.isEmpty(query) || query.length() == 1 || nonDialableQueryInRegularSearch) { return Collections.emptyList(); } List actions = new ArrayList<>(); - actions.add(Action.CREATE_NEW_CONTACT); - actions.add(Action.ADD_TO_CONTACT); + if (!isRegularSearch()) { + actions.add(Action.CREATE_NEW_CONTACT); + actions.add(Action.ADD_TO_CONTACT); + } + + if (isRegularSearch() && isDialableNumber) { + actions.add(Action.MAKE_VOICE_CALL); + } + actions.add(Action.SEND_SMS); if (CallUtil.isVideoEnabled(getContext())) { actions.add(Action.MAKE_VILTE_CALL); } + return actions; } diff --git a/java/com/android/dialer/searchfragment/list/SearchActionViewHolder.java b/java/com/android/dialer/searchfragment/list/SearchActionViewHolder.java index b557a8259..76c71d6ac 100644 --- a/java/com/android/dialer/searchfragment/list/SearchActionViewHolder.java +++ b/java/com/android/dialer/searchfragment/list/SearchActionViewHolder.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.support.annotation.IntDef; import android.support.annotation.StringRes; +import android.support.annotation.VisibleForTesting; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.View.OnClickListener; @@ -49,7 +50,8 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On Action.CREATE_NEW_CONTACT, Action.ADD_TO_CONTACT, Action.SEND_SMS, - Action.MAKE_VILTE_CALL + Action.MAKE_VILTE_CALL, + Action.MAKE_VOICE_CALL }) @interface Action { int INVALID = 0; @@ -61,6 +63,8 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On int SEND_SMS = 3; /** Attempts to make a VILTE call to the number. */ int MAKE_VILTE_CALL = 4; + /** Places a voice call to the number. */ + int MAKE_VOICE_CALL = 5; } private final Context context; @@ -70,6 +74,7 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On private @Action int action; private int position; private String query; + private CallInitiationType.Type callInitiationType; SearchActionViewHolder(View view) { super(view); @@ -79,10 +84,11 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On view.setOnClickListener(this); } - void setAction(@Action int action, int position, String query) { + void setAction(@Action int action, int position, String query, CallInitiationType.Type type) { this.action = action; this.position = position; this.query = query; + this.callInitiationType = type; switch (action) { case Action.ADD_TO_CONTACT: actionText.setText(R.string.search_shortcut_add_to_contact); @@ -100,12 +106,23 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On actionText.setText(R.string.search_shortcut_send_sms_message); actionImage.setImageResource(R.drawable.quantum_ic_message_vd_theme_24); break; + case Action.MAKE_VOICE_CALL: + actionText.setText(context.getString(R.string.search_shortcut_make_voice_call, query)); + actionImage.setImageResource(R.drawable.quantum_ic_phone_vd_theme_24); + break; case Action.INVALID: default: throw Assert.createIllegalStateFailException("Invalid action: " + action); + } } + @VisibleForTesting + @Action + int getAction() { + return action; + } + @Override public void onClick(View v) { switch (action) { @@ -123,14 +140,14 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On break; case Action.MAKE_VILTE_CALL: - CallSpecificAppData callSpecificAppData = + CallSpecificAppData videoCallSpecificAppData = CallSpecificAppData.newBuilder() - .setCallInitiationType(CallInitiationType.Type.DIALPAD) + .setCallInitiationType(callInitiationType) .setPositionOfSelectedSearchResult(position) .setCharactersInSearchString(query.length()) .build(); PreCall.start( - context, new CallIntentBuilder(query, callSpecificAppData).setIsVideoCall(true)); + context, new CallIntentBuilder(query, videoCallSpecificAppData).setIsVideoCall(true)); break; case Action.SEND_SMS: @@ -138,6 +155,16 @@ final class SearchActionViewHolder extends RecyclerView.ViewHolder implements On DialerUtils.startActivityWithErrorToast(context, intent); break; + case Action.MAKE_VOICE_CALL: + CallSpecificAppData voiceCallSpecificAppData = + CallSpecificAppData.newBuilder() + .setCallInitiationType(callInitiationType) + .setPositionOfSelectedSearchResult(position) + .setCharactersInSearchString(query.length()) + .build(); + PreCall.start(context, new CallIntentBuilder(query, voiceCallSpecificAppData)); + break; + case Action.INVALID: default: throw Assert.createIllegalStateFailException("Invalid action: " + action); diff --git a/java/com/android/dialer/searchfragment/list/SearchAdapter.java b/java/com/android/dialer/searchfragment/list/SearchAdapter.java index 17cab6db1..1681097bf 100644 --- a/java/com/android/dialer/searchfragment/list/SearchAdapter.java +++ b/java/com/android/dialer/searchfragment/list/SearchAdapter.java @@ -26,6 +26,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.common.Assert; import com.android.dialer.searchfragment.common.RowClickListener; import com.android.dialer.searchfragment.common.SearchCursor; @@ -47,6 +48,7 @@ public final class SearchAdapter extends RecyclerView.Adapter { // Raw query number from dialpad, which may contain special character such as "+". This is used // for actions to add contact or send sms. private String rawNumber; + private CallInitiationType.Type callInitiationType; private OnClickListener allowClickListener; private OnClickListener dismissClickListener; private RowClickListener rowClickListener; @@ -113,7 +115,8 @@ public final class SearchAdapter extends RecyclerView.Adapter { .setAction( searchCursorManager.getSearchAction(position), position, - TextUtils.isEmpty(rawNumber) ? query : rawNumber); + TextUtils.isEmpty(rawNumber) ? query : rawNumber, + callInitiationType); } else if (holder instanceof LocationPermissionViewHolder) { // No-op } else { @@ -143,16 +146,17 @@ public final class SearchAdapter extends RecyclerView.Adapter { /** * @param visible If true and query is empty, the adapter won't show any list elements. - * @see #setQuery(String) + * @see #setQuery(String, String, CallInitiationType.Type) * @see #getItemCount() */ public void setZeroSuggestVisible(boolean visible) { showZeroSuggest = visible; } - public void setQuery(String query, @Nullable String rawNumber) { + public void setQuery(String query, @Nullable String rawNumber, CallInitiationType.Type type) { this.query = query; this.rawNumber = rawNumber; + this.callInitiationType = type; if (searchCursorManager.setQuery(query)) { notifyDataSetChanged(); } diff --git a/java/com/android/dialer/searchfragment/list/res/values/strings.xml b/java/com/android/dialer/searchfragment/list/res/values/strings.xml index ea238fc92..26685a657 100644 --- a/java/com/android/dialer/searchfragment/list/res/values/strings.xml +++ b/java/com/android/dialer/searchfragment/list/res/values/strings.xml @@ -14,7 +14,7 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License --> - + To search your contacts, turn on the Contacts permissions. @@ -31,4 +31,7 @@ Make video call + + + Call %1$s diff --git a/java/com/android/dialer/searchfragment/testing/TestCursorSchema.java b/java/com/android/dialer/searchfragment/testing/TestCursorSchema.java deleted file mode 100644 index 9117f72cd..000000000 --- a/java/com/android/dialer/searchfragment/testing/TestCursorSchema.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.searchfragment.testing; - -import android.provider.ContactsContract.Data; - -/** Testing class containing cp2 cursor testing utilities. */ -public final class TestCursorSchema { - - /** - * If new rows are added to {@link - * com.android.dialer.searchfragment.common.Projections#CP2_PROJECTION}, this schema should be - * updated. - */ - // TODO(67909522): remove these extra columns and remove all references to "Phone." - public static final String[] SCHEMA = - new String[] { - Data._ID, // 0 - "data2", // 1 Phone Type - "data3", // 2 Phone Label - "data1", // 3 Phone Number, Organization Company - Data.DISPLAY_NAME_PRIMARY, // 4 - Data.PHOTO_ID, // 5 - Data.PHOTO_THUMBNAIL_URI, // 6 - Data.LOOKUP_KEY, // 7 - Data.CARRIER_PRESENCE, // 8 - Data.CONTACT_ID, // 9 - Data.MIMETYPE, // 10 - Data.SORT_KEY_PRIMARY, // 11 - "company_name", // 12, no constant because Organization.COMPANY.equals("data1") - "nick_name" // 13, no constant because Nickname.NAME.equals("data1") - }; -} diff --git a/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java b/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java deleted file mode 100644 index 7e6299eac..000000000 --- a/java/com/android/dialer/searchfragment/testing/TestSearchCursor.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.searchfragment.testing; - -import android.database.Cursor; -import android.database.MatrixCursor; -import android.database.MergeCursor; -import android.support.annotation.Nullable; -import com.android.dialer.searchfragment.common.SearchCursor; - -/** {@link SearchCursor} implementation useful for testing with a header inserted at position 0. */ -public final class TestSearchCursor extends MergeCursor implements SearchCursor { - - public static TestSearchCursor newInstance(Cursor cursor, String header) { - MatrixCursor headerRow = new MatrixCursor(HEADER_PROJECTION); - headerRow.addRow(new String[] {header}); - return new TestSearchCursor(new Cursor[] {headerRow, cursor}); - } - - private TestSearchCursor(Cursor[] cursors) { - super(cursors); - } - - @Override - public boolean isHeader() { - return isFirst(); - } - - @Override - public boolean updateQuery(@Nullable String query) { - return false; - } - - @Override - public long getDirectoryId() { - return 0; - } -} -- cgit v1.2.3