Commit 81959047 authored by Clemens Arbesser's avatar Clemens Arbesser Committed by Commit Bot

[Autofill Assistant] Allow multiple chips in the header.

This CL allows the header to support a full carousel.

What it does:
 - Move header chip logic into native.
 - Use RecyclerView instead of hard-coded single chip view.
 - Potentially fixes an issue where the status message does not stretch
across the whole available width.
 - Chips in the header now support change animations.

There is an issue caused by a layout resize when switching between PEEK
and non-PEEK mode. This is further discussed in the linked bug. The
workaround is to delay the layout resize until the sheet state has
settled.

Bug: b/160856358
Change-Id: Id7617ed41119b85fdaa00ebaff7e856984b74b0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2288567
Commit-Queue: Clemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarMathias Carlen <mcarlen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#796376}
parent 8616745b
......@@ -8,6 +8,7 @@
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/header_top_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="56dp"
......
......@@ -151,6 +151,8 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
// We don't want to animate the carousels children views as they are already animated by the
// recyclers ItemAnimator, so we exclude them to avoid a clash between the animations.
mLayoutTransition.excludeChildren(mActionsCoordinator.getView(), /* exclude= */ true);
mLayoutTransition.excludeChildren(
mHeaderCoordinator.getCarouselView(), /* exclude= */ true);
// do not animate the contents of the payment method section inside the section choice list,
// since the animation is not required and causes a rendering crash.
......@@ -190,7 +192,11 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
controller.addObserver(new EmptyBottomSheetObserver() {
@Override
public void onSheetStateChanged(int newState) {
maybeShowHeaderChip();
// Note: recycler view updates while the bottom sheet is SCROLLING result in a
// BottomSheet assertion.
if (newState != BottomSheetController.SheetState.SCROLLING) {
maybeShowHeaderChips();
}
}
@Override
......@@ -256,10 +262,8 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
}
private void setupAnimations(AssistantModel model, ViewGroup rootView) {
// Animate when the chip in the header changes.
model.getHeaderModel().addObserver((source, propertyKey) -> {
if (propertyKey == AssistantHeaderModel.CHIP
|| propertyKey == AssistantHeaderModel.CHIP_VISIBLE) {
if (propertyKey == AssistantHeaderModel.CHIPS_VISIBLE) {
animateChildren(rootView);
}
});
......@@ -295,12 +299,12 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
TransitionManager.beginDelayedTransition(rootView, mLayoutTransition);
}
private void maybeShowHeaderChip() {
boolean showChip =
private void maybeShowHeaderChips() {
boolean showChips =
mBottomSheetController.getSheetState() == BottomSheetController.SheetState.PEEK
&& mPeekHeightCoordinator.getPeekMode()
== AssistantPeekHeightCoordinator.PeekMode.HANDLE_HEADER;
mModel.getHeaderModel().set(AssistantHeaderModel.CHIP_VISIBLE, showChip);
mModel.getHeaderModel().set(AssistantHeaderModel.CHIPS_VISIBLE, showChips);
}
/**
......@@ -350,7 +354,7 @@ class AssistantBottomBarCoordinator implements AssistantPeekHeightCoordinator.De
/** Set the peek mode. */
void setPeekMode(@AssistantPeekHeightCoordinator.PeekMode int peekMode) {
mPeekHeightCoordinator.setPeekMode(peekMode);
maybeShowHeaderChip();
maybeShowHeaderChips();
}
/** Expand the bottom sheet. */
......
......@@ -18,7 +18,6 @@ import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselModel;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip.Type;
import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel;
import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.profiles.Profile;
......@@ -283,55 +282,56 @@ public class AutofillAssistantUiController {
}
/**
* Adds an action button to the chip list, which executes the action {@code actionIndex}.
* Creates an action button which executes the action {@code actionIndex}.
*/
@CalledByNative
private void addActionButton(List<AssistantChip> chips, int icon, String text, int actionIndex,
private AssistantChip createActionButton(int icon, String text, int actionIndex,
boolean disabled, boolean sticky, String identifier) {
chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled,
sticky, identifier, () -> safeNativeOnUserActionSelected(actionIndex)));
return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky,
identifier, () -> safeNativeOnUserActionSelected(actionIndex));
}
/**
* Adds a highlighted action button to the chip list, which executes the action {@code
* actionIndex}.
* Creates a highlighted action button which executes the action {@code actionIndex}.
*/
@CalledByNative
private void addHighlightedActionButton(List<AssistantChip> chips, int icon, String text,
int actionIndex, boolean disabled, boolean sticky, String identifier) {
chips.add(new AssistantChip(Type.BUTTON_FILLED_BLUE, icon, text, disabled, sticky,
identifier, () -> safeNativeOnUserActionSelected(actionIndex)));
private AssistantChip createHighlightedActionButton(int icon, String text, int actionIndex,
boolean disabled, boolean sticky, String identifier) {
return new AssistantChip(Type.BUTTON_FILLED_BLUE, icon, text, disabled, sticky, identifier,
() -> safeNativeOnUserActionSelected(actionIndex));
}
/**
* Adds a cancel action button to the chip list. If the keyboard is currently shown, it
* dismisses the keyboard. Otherwise, it shows the snackbar and then executes
* {@code actionIndex}, or shuts down Autofill Assistant if {@code actionIndex} is {@code -1}.
* Creates a cancel action button. If the keyboard is currently shown, it dismisses the
* keyboard. Otherwise, it shows the snackbar and then executes {@code actionIndex}, or shuts
* down Autofill Assistant if {@code actionIndex} is {@code -1}.
*/
@CalledByNative
private void addCancelButton(List<AssistantChip> chips, int icon, String text, int actionIndex,
private AssistantChip createCancelButton(int icon, String text, int actionIndex,
boolean disabled, boolean sticky, String identifier) {
chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled,
sticky, identifier, () -> safeNativeOnCancelButtonClicked(actionIndex)));
return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky,
identifier, () -> safeNativeOnCancelButtonClicked(actionIndex));
}
/**
* Adds a close action button to the chip list, which shuts down Autofill Assistant.
*/
@CalledByNative
private void addCloseButton(List<AssistantChip> chips, int icon, String text, boolean disabled,
boolean sticky, String identifier) {
chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled,
sticky, identifier, this::safeNativeOnCloseButtonClicked));
private AssistantChip createCloseButton(
int icon, String text, boolean disabled, boolean sticky, String identifier) {
return new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, icon, text, disabled, sticky,
identifier, this::safeNativeOnCloseButtonClicked);
}
@CalledByNative
private static void appendChipToList(List<AssistantChip> chips, AssistantChip chip) {
chips.add(chip);
}
@CalledByNative
private void setActions(List<AssistantChip> chips) {
// TODO(b/144075373): Move this to AssistantCarouselModel and AssistantHeaderModel. Move
// header chip logic to native.
AssistantCarouselModel model = getModel().getActionsModel();
model.setChips(chips);
setHeaderChip(chips);
// TODO(b/144075373): Move this to AssistantCarouselModel.
getModel().getActionsModel().setChips(chips);
}
@CalledByNative
......@@ -358,19 +358,6 @@ public class AutofillAssistantUiController {
model.setChips(newChips);
}
private void setHeaderChip(List<AssistantChip> chips) {
// The header chip is the first sticky chip found in the actions.
AssistantChip headerChip = null;
for (AssistantChip chip : chips) {
if (chip.isSticky()) {
headerChip = chip;
break;
}
}
getModel().getHeaderModel().set(AssistantHeaderModel.CHIP, headerChip);
}
@CalledByNative
private void setViewportMode(@AssistantViewportMode int mode) {
mCoordinator.getBottomBarCoordinator().setViewportMode(mode);
......
......@@ -22,7 +22,7 @@ import java.util.List;
public class AssistantChipAdapter extends RecyclerView.Adapter<AssistantChipViewHolder> {
private final List<AssistantChip> mChips = new ArrayList<>();
void setChips(List<AssistantChip> chips) {
public void setChips(List<AssistantChip> chips) {
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
......
......@@ -5,13 +5,19 @@
package org.chromium.chrome.browser.autofill_assistant.header;
import android.content.Context;
import android.graphics.Rect;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiController;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipAdapter;
import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderViewBinder.ViewHolder;
import org.chromium.chrome.browser.signin.DisplayableProfileData;
import org.chromium.chrome.browser.signin.IdentityServicesProvider;
......@@ -32,6 +38,7 @@ public class AssistantHeaderCoordinator implements ProfileDataCache.Observer {
private final ImageView mProfileView;
private final String mSignedInAccountName;
private final ViewHolder mViewHolder;
private final RecyclerView mChipsContainer;
public AssistantHeaderCoordinator(Context context, AssistantHeaderModel model) {
// Create the poodle and insert it before the status message. We have to create a view
......@@ -56,8 +63,52 @@ public class AssistantHeaderCoordinator implements ProfileDataCache.Observer {
identityManager.getPrimaryAccountInfo(ConsentLevel.SYNC));
setupProfileImage();
mChipsContainer = new RecyclerView(context);
final int innerChipSpacing = context.getResources().getDimensionPixelSize(
R.dimen.autofill_assistant_actions_spacing);
mChipsContainer.addItemDecoration(new RecyclerView.ItemDecoration() {
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
@NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
outRect.top = 0;
outRect.bottom = 0;
if (state.getItemCount() <= 1) {
return;
}
// If old position != NO_POSITION, it means the carousel is being animated and we
// should use that position in our logic.
int position = parent.getChildAdapterPosition(view);
RecyclerView.ViewHolder viewHolder = parent.getChildViewHolder(view);
if (viewHolder != null && viewHolder.getOldPosition() != RecyclerView.NO_POSITION) {
position = viewHolder.getOldPosition();
}
if (position == RecyclerView.NO_POSITION) {
return;
}
outRect.left = position == 0 ? 0 : innerChipSpacing;
outRect.right = 0;
}
});
AssistantChipAdapter chipAdapter = new AssistantChipAdapter();
mChipsContainer.setAdapter(chipAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
mChipsContainer.setLayoutManager(layoutManager);
mView.setPadding(mChipsContainer.getPaddingLeft(), mChipsContainer.getPaddingTop(),
context.getResources().getDimensionPixelSize(
R.dimen.autofill_assistant_profile_icon_padding),
mChipsContainer.getPaddingBottom());
ViewGroup topContainer = mView.findViewById(R.id.header_top_container);
topContainer.addView(mChipsContainer);
// Bind view and mediator through the model.
mViewHolder = new AssistantHeaderViewBinder.ViewHolder(context, mView, poodle);
mViewHolder =
new AssistantHeaderViewBinder.ViewHolder(context, mView, poodle, mChipsContainer);
AssistantHeaderViewBinder viewBinder = new AssistantHeaderViewBinder();
PropertyModelChangeProcessor.create(model, mViewHolder, viewBinder);
......@@ -77,6 +128,11 @@ public class AssistantHeaderCoordinator implements ProfileDataCache.Observer {
return mView;
}
/** Returns the view containing the chips. */
public View getCarouselView() {
return mChipsContainer;
}
/**
* Cleanup resources when this goes out of scope.
*/
......
......@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.autofill_assistant.header;
import android.support.annotation.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip;
......@@ -18,6 +20,9 @@ import java.util.List;
*/
@JNINamespace("autofill_assistant")
public class AssistantHeaderModel extends PropertyModel {
public static final WritableObjectPropertyKey<List<AssistantChip>> CHIPS =
new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<String> STATUS_MESSAGE =
new WritableObjectPropertyKey<>();
......@@ -45,10 +50,7 @@ public class AssistantHeaderModel extends PropertyModel {
public static final WritableObjectPropertyKey<Runnable> FEEDBACK_BUTTON_CALLBACK =
new WritableObjectPropertyKey<>();
public static final WritableObjectPropertyKey<AssistantChip> CHIP =
new WritableObjectPropertyKey<>();
public static final WritableBooleanPropertyKey CHIP_VISIBLE = new WritableBooleanPropertyKey();
public static final WritableBooleanPropertyKey CHIPS_VISIBLE = new WritableBooleanPropertyKey();
public static final WritableBooleanPropertyKey DISABLE_ANIMATIONS_FOR_TESTING =
new WritableBooleanPropertyKey();
......@@ -56,7 +58,8 @@ public class AssistantHeaderModel extends PropertyModel {
public AssistantHeaderModel() {
super(STATUS_MESSAGE, BUBBLE_MESSAGE, PROGRESS, PROGRESS_ACTIVE_STEP, PROGRESS_BAR_ERROR,
PROGRESS_VISIBLE, USE_STEP_PROGRESS_BAR, STEP_PROGRESS_BAR_ICONS, SPIN_POODLE,
FEEDBACK_BUTTON_CALLBACK, CHIP, CHIP_VISIBLE, DISABLE_ANIMATIONS_FOR_TESTING);
FEEDBACK_BUTTON_CALLBACK, CHIPS, CHIPS_VISIBLE, DISABLE_ANIMATIONS_FOR_TESTING);
set(CHIPS, new ArrayList<>());
}
@CalledByNative
......@@ -127,4 +130,16 @@ public class AssistantHeaderModel extends PropertyModel {
private void setDisableAnimations(boolean disableAnimations) {
set(DISABLE_ANIMATIONS_FOR_TESTING, disableAnimations);
}
@CalledByNative
@VisibleForTesting
public void setChips(List<AssistantChip> chips) {
// Move last chip (cancel) to first position. For legacy reasons, native builds this list
// such that the cancel chip is last, but the regular carousel will show it in the left-most
// position and the header should mirror this.
if (chips.size() > 1) {
chips.add(0, chips.remove(chips.size() - 1));
}
set(CHIPS, chips);
}
}
......@@ -11,11 +11,12 @@ import android.widget.PopupMenu;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipViewHolder;
import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipAdapter;
import org.chromium.chrome.browser.settings.SettingsLauncher;
import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
......@@ -45,12 +46,12 @@ class AssistantHeaderViewBinder
final AssistantStepProgressBar mStepProgressBar;
final View mProfileIconView;
final PopupMenu mProfileIconMenu;
@Nullable
AssistantChipViewHolder mChip;
final RecyclerView mChipsContainer;
@Nullable
TextBubble mTextBubble;
ViewHolder(Context context, ViewGroup headerView, AnimatedPoodle poodle) {
ViewHolder(Context context, ViewGroup headerView, AnimatedPoodle poodle,
RecyclerView chipsContainer) {
mContext = context;
mPoodle = poodle;
mHeader = headerView;
......@@ -62,6 +63,7 @@ class AssistantHeaderViewBinder
mProfileIconMenu = new PopupMenu(context, mProfileIconView);
mProfileIconMenu.inflate(R.menu.profile_icon_menu);
mProfileIconView.setOnClickListener(unusedView -> mProfileIconMenu.show());
mChipsContainer = chipsContainer;
}
void disableAnimations(boolean disable) {
......@@ -70,6 +72,8 @@ class AssistantHeaderViewBinder
// Hiding the animated poodle seems to be the easiest way to disable its animation since
// {@link LogoView#setAnimationEnabled(boolean)} is private.
mPoodle.getView().setVisibility(View.INVISIBLE);
((DefaultItemAnimator) mChipsContainer.getItemAnimator())
.setSupportsChangeAnimations(!disable);
}
void updateProgressBarVisibility(boolean visible, boolean useStepProgressBar) {
......@@ -110,11 +114,13 @@ class AssistantHeaderViewBinder
view.mPoodle.setSpinEnabled(model.get(AssistantHeaderModel.SPIN_POODLE));
} else if (AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK == propertyKey) {
setProfileMenuListener(view, model.get(AssistantHeaderModel.FEEDBACK_BUTTON_CALLBACK));
} else if (AssistantHeaderModel.CHIP == propertyKey) {
bindChip(view, model.get(AssistantHeaderModel.CHIP));
maybeShowChip(model, view);
} else if (AssistantHeaderModel.CHIP_VISIBLE == propertyKey) {
maybeShowChip(model, view);
} else if (AssistantHeaderModel.CHIPS == propertyKey) {
view.mChipsContainer.invalidateItemDecorations();
((AssistantChipAdapter) view.mChipsContainer.getAdapter())
.setChips(model.get(AssistantHeaderModel.CHIPS));
maybeShowChips(model, view);
} else if (AssistantHeaderModel.CHIPS_VISIBLE == propertyKey) {
maybeShowChips(model, view);
} else if (AssistantHeaderModel.BUBBLE_MESSAGE == propertyKey) {
showOrDismissBubble(model, view);
} else if (AssistantHeaderModel.DISABLE_ANIMATIONS_FOR_TESTING == propertyKey) {
......@@ -124,45 +130,18 @@ class AssistantHeaderViewBinder
}
}
private void maybeShowChip(AssistantHeaderModel model, ViewHolder view) {
if (model.get(AssistantHeaderModel.CHIP_VISIBLE)
&& model.get(AssistantHeaderModel.CHIP) != null) {
view.mChip.getView().setVisibility(View.VISIBLE);
private void maybeShowChips(AssistantHeaderModel model, ViewHolder view) {
if (model.get(AssistantHeaderModel.CHIPS_VISIBLE)
&& !model.get(AssistantHeaderModel.CHIPS).isEmpty()) {
view.mChipsContainer.setVisibility(View.VISIBLE);
view.mProfileIconView.setVisibility(View.GONE);
} else {
if (view.mChip != null) {
view.mChip.getView().setVisibility(View.GONE);
}
view.mChipsContainer.setVisibility(View.GONE);
view.mProfileIconView.setVisibility(View.VISIBLE);
}
}
private void bindChip(ViewHolder view, @Nullable AssistantChip chip) {
if (chip == null) {
return;
}
int viewType = AssistantChipViewHolder.getViewType(chip);
// If there is already a chip in the header but with incompatible type, remove it.
ViewGroup parent = (ViewGroup) view.mStatusMessage.getParent();
if (view.mChip != null && view.mChip.getType() != viewType) {
parent.removeView(view.mChip.getView());
view.mChip = null;
}
// If there is no chip already in the header, create one and add it at the end of the
// header.
if (view.mChip == null) {
view.mChip = AssistantChipViewHolder.create(view.mHeader, viewType);
parent.addView(view.mChip.getView());
}
// Bind the chip to the view.
view.mChip.bind(chip);
}
private void setProfileMenuListener(ViewHolder view, @Nullable Runnable feedbackCallback) {
view.mProfileIconMenu.setOnMenuItemClickListener(item -> {
int itemId = item.getItemId();
......
......@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.autofill_assistant;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.assertion.PositionAssertions.isRightOf;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
......@@ -52,6 +53,9 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.components.browser_ui.widget.MaterialProgressBar;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Tests for the Autofill Assistant header.
*/
......@@ -206,15 +210,17 @@ public class AutofillAssistantHeaderUiTest {
chipText, /* disabled= */ false, /* sticky= */ false, "", () -> {});
// Set the header chip without displaying it.
TestThreadUtils.runOnUiThreadBlocking(() -> model.set(AssistantHeaderModel.CHIP, chip));
List<AssistantChip> chips = new ArrayList<>();
chips.add(chip);
TestThreadUtils.runOnUiThreadBlocking(() -> model.setChips(chips));
Matcher<View> chipMatcher =
allOf(isDescendantOfA(is(coordinator.getView())), withText(chipText));
onView(chipMatcher).check(matches(not(isDisplayed())));
onView(chipMatcher).check(doesNotExist());
// Show the chip
TestThreadUtils.runOnUiThreadBlocking(
() -> model.set(AssistantHeaderModel.CHIP_VISIBLE, true));
() -> model.set(AssistantHeaderModel.CHIPS_VISIBLE, true));
onView(chipMatcher)
.check(matches(isDisplayed()))
.check(isRightOf(withId(R.id.status_message)));
......
......@@ -678,11 +678,13 @@ void UiControllerAndroid::UpdateActions(
JNIEnv* env = AttachCurrentThread();
bool has_close_or_cancel = false;
auto chips = Java_AutofillAssistantUiController_createChipList(env);
auto jchips = Java_AutofillAssistantUiController_createChipList(env);
auto jsticky_chips = Java_AutofillAssistantUiController_createChipList(env);
int user_action_count = static_cast<int>(user_actions.size());
for (int i = 0; i < user_action_count; i++) {
const auto& action = user_actions[i];
const Chip& chip = action.chip();
base::android::ScopedJavaLocalRef<jobject> jchip;
switch (chip.type) {
default: // Ignore actions with other chip types or with no chips.
break;
......@@ -692,16 +694,17 @@ void UiControllerAndroid::UpdateActions(
// can hide all the chips except for the cancel chip when the keyboard
// is showing.
// TODO(b/149543425): Find a better way to do this.
Java_AutofillAssistantUiController_addHighlightedActionButton(
env, java_object_, chips, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
jchip =
Java_AutofillAssistantUiController_createHighlightedActionButton(
env, java_object_, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
break;
case NORMAL_ACTION:
Java_AutofillAssistantUiController_addActionButton(
env, java_object_, chips, chip.icon,
jchip = Java_AutofillAssistantUiController_createActionButton(
env, java_object_, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
......@@ -710,8 +713,8 @@ void UiControllerAndroid::UpdateActions(
case CANCEL_ACTION:
// A Cancel button sneaks in an UNDO snackbar before executing the
// action, while a close button behaves like a normal button.
Java_AutofillAssistantUiController_addCancelButton(
env, java_object_, chips, chip.icon,
jchip = Java_AutofillAssistantUiController_createCancelButton(
env, java_object_, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, kCancelChipIdentifier));
......@@ -719,8 +722,8 @@ void UiControllerAndroid::UpdateActions(
break;
case CLOSE_ACTION:
Java_AutofillAssistantUiController_addActionButton(
env, java_object_, chips, chip.icon,
jchip = Java_AutofillAssistantUiController_createActionButton(
env, java_object_, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
......@@ -728,33 +731,50 @@ void UiControllerAndroid::UpdateActions(
break;
case DONE_ACTION:
Java_AutofillAssistantUiController_addHighlightedActionButton(
env, java_object_, chips, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
jchip =
Java_AutofillAssistantUiController_createHighlightedActionButton(
env, java_object_, chip.icon,
base::android::ConvertUTF8ToJavaString(env, chip.text), i,
!action.enabled(), chip.sticky,
base::android::ConvertUTF8ToJavaString(env, ""));
has_close_or_cancel = true;
break;
}
if (jchip) {
Java_AutofillAssistantUiController_appendChipToList(env, jchips, jchip);
if (chip.sticky) {
Java_AutofillAssistantUiController_appendChipToList(env, jsticky_chips,
jchip);
}
}
}
if (!has_close_or_cancel) {
base::android::ScopedJavaLocalRef<jobject> jcancel_chip;
if (ui_delegate_->GetState() == AutofillAssistantState::STOPPED) {
Java_AutofillAssistantUiController_addCloseButton(
env, java_object_, chips, ICON_CLEAR,
jcancel_chip = Java_AutofillAssistantUiController_createCloseButton(
env, java_object_, ICON_CLEAR,
base::android::ConvertUTF8ToJavaString(env, ""),
/* disabled= */ false, /* sticky= */ true,
base::android::ConvertUTF8ToJavaString(env, ""));
} else if (ui_delegate_->GetState() != AutofillAssistantState::INACTIVE) {
Java_AutofillAssistantUiController_addCancelButton(
env, java_object_, chips, ICON_CLEAR,
jcancel_chip = Java_AutofillAssistantUiController_createCancelButton(
env, java_object_, ICON_CLEAR,
base::android::ConvertUTF8ToJavaString(env, ""), -1,
/* disabled= */ false, /* sticky= */ true,
base::android::ConvertUTF8ToJavaString(env, kCancelChipIdentifier));
}
if (jcancel_chip) {
Java_AutofillAssistantUiController_appendChipToList(env, jchips,
jcancel_chip);
Java_AutofillAssistantUiController_appendChipToList(env, jsticky_chips,
jcancel_chip);
}
}
Java_AutofillAssistantUiController_setActions(env, java_object_, chips);
Java_AutofillAssistantUiController_setActions(env, java_object_, jchips);
Java_AssistantHeaderModel_setChips(AttachCurrentThread(), GetHeaderModel(),
jsticky_chips);
}
void UiControllerAndroid::OnUserActionsChanged(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment