Remove items on long press in keyboard accessory.
BUG=428087 Review URL: https://codereview.chromium.org/1281323003 Cr-Commit-Position: refs/heads/master@{#343764}
This commit is contained in:
android_webview/java/src/org/chromium/android_webview
chrome
android
java
src
org
chromium
chrome
browser
javatests
src
org
chromium
chrome
browser
autofill
browser
ui/android/java/src/org/chromium/ui/autofill
@ -10,6 +10,7 @@ import org.chromium.base.annotations.CalledByNative;
|
||||
import org.chromium.base.annotations.JNINamespace;
|
||||
import org.chromium.content.browser.ContentViewCore;
|
||||
import org.chromium.ui.DropdownItem;
|
||||
import org.chromium.ui.autofill.AutofillDelegate;
|
||||
import org.chromium.ui.autofill.AutofillPopup;
|
||||
import org.chromium.ui.autofill.AutofillSuggestion;
|
||||
|
||||
@ -49,7 +50,7 @@ public class AwAutofillClient {
|
||||
mAutofillPopup = new AutofillPopup(
|
||||
mContentViewCore.getContext(),
|
||||
mContentViewCore.getViewAndroidDelegate(),
|
||||
new AutofillPopup.AutofillPopupDelegate() {
|
||||
new AutofillDelegate() {
|
||||
@Override
|
||||
public void dismissed() { }
|
||||
@Override
|
||||
|
44
chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java
44
chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillKeyboardAccessoryBridge.java
@ -4,12 +4,17 @@
|
||||
|
||||
package org.chromium.chrome.browser.autofill;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import org.chromium.base.annotations.CalledByNative;
|
||||
import org.chromium.base.annotations.JNINamespace;
|
||||
import org.chromium.chrome.R;
|
||||
import org.chromium.chrome.browser.ResourceId;
|
||||
import org.chromium.ui.DropdownItem;
|
||||
import org.chromium.ui.autofill.AutofillDelegate;
|
||||
import org.chromium.ui.autofill.AutofillKeyboardAccessory;
|
||||
import org.chromium.ui.autofill.AutofillKeyboardAccessory.AutofillKeyboardAccessoryDelegate;
|
||||
import org.chromium.ui.autofill.AutofillSuggestion;
|
||||
import org.chromium.ui.base.WindowAndroid;
|
||||
|
||||
@ -19,9 +24,11 @@ import org.chromium.ui.base.WindowAndroid;
|
||||
* --enable-autofill-keyboard-accessory-view is passed on the command line.
|
||||
*/
|
||||
@JNINamespace("autofill")
|
||||
public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessoryDelegate {
|
||||
public class AutofillKeyboardAccessoryBridge
|
||||
implements AutofillDelegate, DialogInterface.OnClickListener {
|
||||
private long mNativeAutofillKeyboardAccessory;
|
||||
private AutofillKeyboardAccessory mAccessoryView;
|
||||
private Context mContext;
|
||||
|
||||
private AutofillKeyboardAccessoryBridge() {
|
||||
}
|
||||
@ -43,6 +50,19 @@ public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessor
|
||||
nativeSuggestionSelected(mNativeAutofillKeyboardAccessory, listIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSuggestion(int listIndex) {
|
||||
if (mNativeAutofillKeyboardAccessory == 0) return;
|
||||
nativeDeletionRequested(mNativeAutofillKeyboardAccessory, listIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
assert which == DialogInterface.BUTTON_POSITIVE;
|
||||
if (mNativeAutofillKeyboardAccessory == 0) return;
|
||||
nativeDeletionConfirmed(mNativeAutofillKeyboardAccessory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this object.
|
||||
* This function should be called at most one time.
|
||||
@ -59,6 +79,7 @@ public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessor
|
||||
|
||||
mNativeAutofillKeyboardAccessory = nativeAutofillKeyboardAccessory;
|
||||
mAccessoryView = new AutofillKeyboardAccessory(windowAndroid, this);
|
||||
mContext = windowAndroid.getActivity().get();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,6 +96,7 @@ public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessor
|
||||
@CalledByNative
|
||||
private void dismiss() {
|
||||
if (mAccessoryView != null) mAccessoryView.dismiss();
|
||||
mContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -90,6 +112,17 @@ public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessor
|
||||
// should
|
||||
// eventually disappear).
|
||||
|
||||
@CalledByNative
|
||||
private void confirmDeletion(String title, String body) {
|
||||
new AlertDialog.Builder(mContext, R.style.AlertDialogTheme)
|
||||
.setTitle(title)
|
||||
.setMessage(body)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setPositiveButton(R.string.ok, this)
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
@CalledByNative
|
||||
private static AutofillSuggestion[] createAutofillSuggestionArray(int size) {
|
||||
return new AutofillSuggestion[size];
|
||||
@ -114,12 +147,15 @@ public class AutofillKeyboardAccessoryBridge implements AutofillKeyboardAccessor
|
||||
*/
|
||||
@CalledByNative
|
||||
private static void addToAutofillSuggestionArray(AutofillSuggestion[] array, int index,
|
||||
String label, String sublabel, int iconId, int suggestionId) {
|
||||
String label, String sublabel, int iconId, int suggestionId, boolean deletable) {
|
||||
int drawableId = iconId == 0 ? DropdownItem.NO_ICON : ResourceId.mapToDrawableId(iconId);
|
||||
array[index] = new AutofillSuggestion(label, sublabel, drawableId, suggestionId, false);
|
||||
array[index] = new AutofillSuggestion(label, sublabel, drawableId, suggestionId, deletable);
|
||||
}
|
||||
|
||||
private native void nativeViewDismissed(long nativeAutofillKeyboardAccessoryView);
|
||||
private native void nativeSuggestionSelected(
|
||||
long nativeAutofillKeyboardAccessoryView, int listIndex);
|
||||
private native void nativeDeletionRequested(
|
||||
long nativeAutofillKeyboardAccessoryView, int listIndex);
|
||||
private native void nativeDeletionConfirmed(long nativeAutofillKeyboardAccessoryView);
|
||||
}
|
||||
|
@ -15,8 +15,8 @@ import org.chromium.base.annotations.JNINamespace;
|
||||
import org.chromium.chrome.R;
|
||||
import org.chromium.chrome.browser.ResourceId;
|
||||
import org.chromium.ui.DropdownItem;
|
||||
import org.chromium.ui.autofill.AutofillDelegate;
|
||||
import org.chromium.ui.autofill.AutofillPopup;
|
||||
import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate;
|
||||
import org.chromium.ui.autofill.AutofillSuggestion;
|
||||
import org.chromium.ui.base.ViewAndroidDelegate;
|
||||
import org.chromium.ui.base.WindowAndroid;
|
||||
@ -25,7 +25,7 @@ import org.chromium.ui.base.WindowAndroid;
|
||||
* JNI call glue for AutofillExternalDelagate C++ and Java objects.
|
||||
*/
|
||||
@JNINamespace("autofill")
|
||||
public class AutofillPopupBridge implements AutofillPopupDelegate, DialogInterface.OnClickListener {
|
||||
public class AutofillPopupBridge implements AutofillDelegate, DialogInterface.OnClickListener {
|
||||
private final long mNativeAutofillPopup;
|
||||
private final AutofillPopup mAutofillPopup;
|
||||
private AlertDialog mDeletionDialog;
|
||||
|
@ -17,8 +17,8 @@ import org.chromium.content.browser.test.util.Criteria;
|
||||
import org.chromium.content.browser.test.util.CriteriaHelper;
|
||||
import org.chromium.content.browser.test.util.TouchCommon;
|
||||
import org.chromium.ui.DropdownItem;
|
||||
import org.chromium.ui.autofill.AutofillDelegate;
|
||||
import org.chromium.ui.autofill.AutofillPopup;
|
||||
import org.chromium.ui.autofill.AutofillPopup.AutofillPopupDelegate;
|
||||
import org.chromium.ui.autofill.AutofillSuggestion;
|
||||
import org.chromium.ui.base.ActivityWindowAndroid;
|
||||
import org.chromium.ui.base.ViewAndroidDelegate;
|
||||
@ -69,7 +69,7 @@ public class AutofillTest extends ChromeActivityTestCaseBase<ChromeActivity> {
|
||||
private static final long CALLBACK_TIMEOUT_MS = scaleTimeout(4000);
|
||||
private static final int CHECK_INTERVAL_MS = 100;
|
||||
|
||||
private class MockAutofillCallback implements AutofillPopupDelegate{
|
||||
private class MockAutofillCallback implements AutofillDelegate {
|
||||
private final AtomicBoolean mGotPopupSelection = new AtomicBoolean(false);
|
||||
public int mListIndex = -1;
|
||||
|
||||
|
@ -22,7 +22,8 @@ namespace autofill {
|
||||
|
||||
AutofillKeyboardAccessoryView::AutofillKeyboardAccessoryView(
|
||||
AutofillPopupController* controller)
|
||||
: controller_(controller) {
|
||||
: controller_(controller),
|
||||
deleting_index_(-1) {
|
||||
JNIEnv* env = base::android::AttachCurrentThread();
|
||||
java_object_.Reset(Java_AutofillKeyboardAccessoryBridge_create(env));
|
||||
}
|
||||
@ -66,11 +67,13 @@ void AutofillKeyboardAccessoryView::UpdateBoundsAndRedrawPopup() {
|
||||
controller_->GetIconResourceID(suggestion.icon));
|
||||
}
|
||||
|
||||
bool deletable =
|
||||
controller_->GetRemovalConfirmationText(i, nullptr, nullptr);
|
||||
Java_AutofillKeyboardAccessoryBridge_addToAutofillSuggestionArray(
|
||||
env, data_array.obj(), i,
|
||||
base::android::ConvertUTF16ToJavaString(env, suggestion.value).obj(),
|
||||
base::android::ConvertUTF16ToJavaString(env, suggestion.label).obj(),
|
||||
android_icon_id, suggestion.frontend_id);
|
||||
android_icon_id, suggestion.frontend_id, deletable);
|
||||
}
|
||||
|
||||
Java_AutofillKeyboardAccessoryBridge_show(
|
||||
@ -85,6 +88,34 @@ void AutofillKeyboardAccessoryView::SuggestionSelected(JNIEnv* env,
|
||||
controller_->AcceptSuggestion(list_index);
|
||||
}
|
||||
|
||||
void AutofillKeyboardAccessoryView::DeletionRequested(JNIEnv* env,
|
||||
jobject obj,
|
||||
jint list_index) {
|
||||
if (!controller_)
|
||||
return;
|
||||
|
||||
base::string16 confirmation_title, confirmation_body;
|
||||
if (!controller_->GetRemovalConfirmationText(list_index, &confirmation_title,
|
||||
&confirmation_body)) {
|
||||
return;
|
||||
}
|
||||
|
||||
deleting_index_ = list_index;
|
||||
Java_AutofillKeyboardAccessoryBridge_confirmDeletion(
|
||||
env, java_object_.obj(),
|
||||
base::android::ConvertUTF16ToJavaString(env, confirmation_title).obj(),
|
||||
base::android::ConvertUTF16ToJavaString(env, confirmation_body).obj());
|
||||
}
|
||||
|
||||
void AutofillKeyboardAccessoryView::DeletionConfirmed(JNIEnv* env,
|
||||
jobject obj) {
|
||||
if (!controller_)
|
||||
return;
|
||||
|
||||
CHECK_GE(deleting_index_, 0);
|
||||
controller_->RemoveSuggestion(deleting_index_);
|
||||
}
|
||||
|
||||
void AutofillKeyboardAccessoryView::ViewDismissed(JNIEnv* env, jobject obj) {
|
||||
if (controller_)
|
||||
controller_->ViewDestroyed();
|
||||
|
@ -33,6 +33,10 @@ class AutofillKeyboardAccessoryView : public AutofillPopupView {
|
||||
// Called when an autofill item was selected.
|
||||
void SuggestionSelected(JNIEnv* env, jobject obj, jint list_index);
|
||||
|
||||
void DeletionRequested(JNIEnv* env, jobject obj, jint list_index);
|
||||
|
||||
void DeletionConfirmed(JNIEnv* env, jobject obj);
|
||||
|
||||
void ViewDismissed(JNIEnv* env, jobject obj);
|
||||
|
||||
static bool RegisterAutofillKeyboardAccessoryView(JNIEnv* env);
|
||||
@ -49,6 +53,10 @@ class AutofillKeyboardAccessoryView : public AutofillPopupView {
|
||||
|
||||
AutofillPopupController* controller_; // weak.
|
||||
|
||||
// The index of the last item the user long-pressed (they will be shown a
|
||||
// confirmation dialog).
|
||||
int deleting_index_;
|
||||
|
||||
// The corresponding java object.
|
||||
base::android::ScopedJavaGlobalRef<jobject> java_object_;
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package org.chromium.ui.autofill;
|
||||
|
||||
/**
|
||||
* An interface to handle the touch interaction with an autofill popup or keyboard accessory.
|
||||
*/
|
||||
public interface AutofillDelegate {
|
||||
/**
|
||||
* Informs the controller the AutofillPopup or AutofillKeyboardAccessory was hidden.
|
||||
*/
|
||||
public void dismissed();
|
||||
|
||||
/**
|
||||
* Handles the selection of an Autofill suggestion from an AutofillPopup or
|
||||
* AutofillKeyboardAccessory.
|
||||
* @param listIndex The index of the selected Autofill suggestion.
|
||||
*/
|
||||
public void suggestionSelected(int listIndex);
|
||||
|
||||
/**
|
||||
* Initiates the deletion process for an item. (A confirm dialog should be shown.)
|
||||
* @param listIndex The index of the suggestion to delete.
|
||||
*/
|
||||
public void deleteSuggestion(int listIndex);
|
||||
}
|
@ -26,41 +26,26 @@ import org.chromium.ui.gfx.DeviceDisplayInfo;
|
||||
* below the content area.
|
||||
*/
|
||||
public class AutofillKeyboardAccessory extends LinearLayout
|
||||
implements WindowAndroid.KeyboardVisibilityListener, View.OnClickListener {
|
||||
implements WindowAndroid.KeyboardVisibilityListener, View.OnClickListener,
|
||||
View.OnLongClickListener {
|
||||
private final WindowAndroid mWindowAndroid;
|
||||
private final AutofillKeyboardAccessoryDelegate mAutofillCallback;
|
||||
private final AutofillDelegate mAutofillDelegate;
|
||||
private final int mMaximumLabelWidthPx;
|
||||
private final int mMaximumSublabelWidthPx;
|
||||
|
||||
/**
|
||||
* An interface to handle the touch interaction with an AutofillKeyboardAccessory object.
|
||||
*/
|
||||
public interface AutofillKeyboardAccessoryDelegate {
|
||||
/**
|
||||
* Informs the controller the AutofillKeyboardAccessory was hidden.
|
||||
*/
|
||||
public void dismissed();
|
||||
|
||||
/**
|
||||
* Handles the selection of an Autofill suggestion from an AutofillKeyboardAccessory.
|
||||
* @param listIndex The index of the selected Autofill suggestion.
|
||||
*/
|
||||
public void suggestionSelected(int listIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AutofillKeyboardAccessory with specified parameters.
|
||||
* @param windowAndroid The owning WindowAndroid.
|
||||
* @param autofillCallback A object that handles the calls to the native
|
||||
* AutofillKeyboardAccessoryView.
|
||||
* @param autofillDelegate A object that handles the calls to the native
|
||||
* AutofillKeyboardAccessoryView.
|
||||
*/
|
||||
public AutofillKeyboardAccessory(
|
||||
WindowAndroid windowAndroid, AutofillKeyboardAccessoryDelegate autofillCallback) {
|
||||
WindowAndroid windowAndroid, AutofillDelegate autofillDelegate) {
|
||||
super(windowAndroid.getActivity().get());
|
||||
assert autofillCallback != null;
|
||||
assert autofillDelegate != null;
|
||||
assert windowAndroid.getActivity().get() != null;
|
||||
mWindowAndroid = windowAndroid;
|
||||
mAutofillCallback = autofillCallback;
|
||||
mAutofillDelegate = autofillDelegate;
|
||||
|
||||
int deviceWidthPx = DeviceDisplayInfo.create(getContext()).getDisplayWidth();
|
||||
mMaximumLabelWidthPx = deviceWidthPx / 2;
|
||||
@ -82,7 +67,8 @@ public class AutofillKeyboardAccessory extends LinearLayout
|
||||
@SuppressLint("InlinedApi")
|
||||
public void showWithSuggestions(AutofillSuggestion[] suggestions, boolean isRtl) {
|
||||
removeAllViews();
|
||||
for (AutofillSuggestion suggestion : suggestions) {
|
||||
for (int i = 0; i < suggestions.length; i++) {
|
||||
AutofillSuggestion suggestion = suggestions[i];
|
||||
assert !TextUtils.isEmpty(suggestion.getLabel());
|
||||
|
||||
View touchTarget;
|
||||
@ -119,7 +105,12 @@ public class AutofillKeyboardAccessory extends LinearLayout
|
||||
}
|
||||
}
|
||||
|
||||
touchTarget.setTag(i);
|
||||
touchTarget.setOnClickListener(this);
|
||||
if (suggestion.isDeletable()) {
|
||||
touchTarget.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
addView(touchTarget);
|
||||
}
|
||||
|
||||
@ -149,20 +140,18 @@ public class AutofillKeyboardAccessory extends LinearLayout
|
||||
public void keyboardVisibilityChanged(boolean isShowing) {
|
||||
if (!isShowing) {
|
||||
dismiss();
|
||||
mAutofillCallback.dismissed();
|
||||
mAutofillDelegate.dismissed();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (getChildAt(i) == v) {
|
||||
mAutofillCallback.suggestionSelected(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
mAutofillDelegate.suggestionSelected((int) v.getTag());
|
||||
}
|
||||
|
||||
assert false;
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
mAutofillDelegate.deleteSuggestion((int) v.getTag());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -34,43 +34,20 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
|
||||
private static final int ITEM_ID_SEPARATOR_ENTRY = -3;
|
||||
|
||||
private final Context mContext;
|
||||
private final AutofillPopupDelegate mAutofillCallback;
|
||||
private final AutofillDelegate mAutofillDelegate;
|
||||
private List<AutofillSuggestion> mSuggestions;
|
||||
|
||||
|
||||
/**
|
||||
* An interface to handle the touch interaction with an AutofillPopup object.
|
||||
*/
|
||||
public interface AutofillPopupDelegate {
|
||||
/**
|
||||
* Informs the controller the AutofillPopup was hidden.
|
||||
*/
|
||||
public void dismissed();
|
||||
|
||||
/**
|
||||
* Handles the selection of an Autofill suggestion from an AutofillPopup.
|
||||
* @param listIndex The index of the selected Autofill suggestion.
|
||||
*/
|
||||
public void suggestionSelected(int listIndex);
|
||||
|
||||
/**
|
||||
* Initiates the deletion process for an item. (A confirm dialog should be shown.)
|
||||
* @param listIndex The index of the suggestion to delete.
|
||||
*/
|
||||
public void deleteSuggestion(int listIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an AutofillWindow with specified parameters.
|
||||
* @param context Application context.
|
||||
* @param viewAndroidDelegate View delegate used to add and remove views.
|
||||
* @param autofillCallback A object that handles the calls to the native AutofillPopupView.
|
||||
* @param autofillDelegate An object that handles the calls to the native AutofillPopupView.
|
||||
*/
|
||||
public AutofillPopup(Context context, ViewAndroidDelegate viewAndroidDelegate,
|
||||
AutofillPopupDelegate autofillCallback) {
|
||||
AutofillDelegate autofillDelegate) {
|
||||
super(context, viewAndroidDelegate);
|
||||
mContext = context;
|
||||
mAutofillCallback = autofillCallback;
|
||||
mAutofillDelegate = autofillDelegate;
|
||||
|
||||
setOnItemClickListener(this);
|
||||
setOnDismissListener(this);
|
||||
@ -109,7 +86,7 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
|
||||
DropdownAdapter adapter = (DropdownAdapter) parent.getAdapter();
|
||||
int listIndex = mSuggestions.indexOf(adapter.getItem(position));
|
||||
assert listIndex > -1;
|
||||
mAutofillCallback.suggestionSelected(listIndex);
|
||||
mAutofillDelegate.suggestionSelected(listIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,12 +97,12 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
|
||||
|
||||
int listIndex = mSuggestions.indexOf(suggestion);
|
||||
assert listIndex > -1;
|
||||
mAutofillCallback.deleteSuggestion(listIndex);
|
||||
mAutofillDelegate.deleteSuggestion(listIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss() {
|
||||
mAutofillCallback.dismissed();
|
||||
mAutofillDelegate.dismissed();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user