Commit 4b2808a6 authored by Clemens Arbesser's avatar Clemens Arbesser Committed by Commit Bot

[Autofill Assistant] Added vertical expanders to ui framework.

Bug: b/145043394
Change-Id: Id61c888bd0b2efb1b0232bb172b8e1613512714b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2115654
Commit-Queue: Clemens Arbesser <arbesser@google.com>
Reviewed-by: default avatarMarian Fechete <marianfe@google.com>
Cr-Commit-Position: refs/heads/master@{#753585}
parent 3cc30059
......@@ -22,6 +22,9 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.autofill.prefeditor.EditorFieldModel;
import org.chromium.chrome.browser.autofill.prefeditor.EditorTextField;
import org.chromium.chrome.browser.autofill_assistant.AssistantChevronStyle;
import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpander;
import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpanderAccordion;
import org.chromium.ui.widget.ChromeImageView;
/** Generic view factory. */
......@@ -159,4 +162,46 @@ public class AssistantViewFactory {
view.setTag(viewIdentifier);
return view;
}
/**
* Creates an {@code AssistantVerticalExpander} widget.
* @param chevronStyle Should match the enum defined in
* components/autofill_assistant/browser/view_layout.proto
*/
@CalledByNative
public static AssistantVerticalExpander createVerticalExpander(Context context,
String identifier, @Nullable View titleView, @Nullable View collapsedView,
@Nullable View expandedView, @AssistantChevronStyle int chevronStyle) {
AssistantVerticalExpander expander = new AssistantVerticalExpander(context, null);
if (titleView != null) {
expander.setTitleView(titleView,
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}
if (collapsedView != null) {
expander.setCollapsedView(collapsedView,
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}
if (expandedView != null) {
expander.setExpandedView(expandedView,
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
}
expander.setChevronStyle(chevronStyle);
expander.setFixed(collapsedView == null || expandedView == null);
expander.setTag(identifier);
return expander;
}
/** Creates an {@code AssistantVerticalExpanderAccordion} widget. */
@CalledByNative
public static AssistantVerticalExpanderAccordion createVerticalExpanderAccordion(
Context context, String identifier, int orientation) {
AssistantVerticalExpanderAccordion accordion =
new AssistantVerticalExpanderAccordion(context, null);
accordion.setOrientation(orientation);
accordion.setTag(identifier);
return accordion;
}
}
......@@ -15,7 +15,7 @@ import androidx.annotation.Nullable;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpander.ChevronStyle;
import org.chromium.chrome.browser.autofill_assistant.AssistantChevronStyle;
import org.chromium.content.browser.input.PopupItemType;
import org.chromium.content.browser.input.SelectPopupDialog;
import org.chromium.content.browser.input.SelectPopupItem;
......@@ -152,7 +152,7 @@ public class AssistantDateSection {
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
expander.setFixed(true);
expander.setChevronStyle(ChevronStyle.ALWAYS);
expander.setChevronStyle(AssistantChevronStyle.ALWAYS);
expander.findViewById(R.id.section_title_add_button).setVisibility(View.GONE);
}
......
......@@ -17,6 +17,7 @@ import android.widget.LinearLayout;
import org.chromium.base.Callback;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.AssistantChevronStyle;
import org.chromium.components.browser_ui.widget.TintedDrawable;
/**
......@@ -28,13 +29,6 @@ import org.chromium.components.browser_ui.widget.TintedDrawable;
* parameters for disambiguation, otherwise the child won't be added at all!
*/
public class AssistantVerticalExpander extends LinearLayout {
/** Controls whether the chevron should be visible. */
public enum ChevronStyle {
AUTO, /** visible if the expander has an expanded view, else invisible. */
ALWAYS,
NEVER
}
private final ViewGroup mTitleContainer;
private final ViewGroup mCollapsedContainer;
private final ViewGroup mExpandedContainer;
......@@ -47,7 +41,7 @@ public class AssistantVerticalExpander extends LinearLayout {
private View mExpandedView;
private boolean mExpanded;
private boolean mFixed;
private ChevronStyle mChevronStyle = ChevronStyle.AUTO;
private @AssistantChevronStyle int mChevronStyle = AssistantChevronStyle.NOT_SET_AUTOMATIC;
public AssistantVerticalExpander(Context context, AttributeSet attrs) {
super(context, attrs);
......@@ -139,9 +133,9 @@ public class AssistantVerticalExpander extends LinearLayout {
}
}
public void setChevronStyle(ChevronStyle style) {
if (style != mChevronStyle) {
mChevronStyle = style;
public void setChevronStyle(@AssistantChevronStyle int chevronStyle) {
if (chevronStyle != mChevronStyle) {
mChevronStyle = chevronStyle;
update();
}
}
......@@ -205,14 +199,14 @@ public class AssistantVerticalExpander extends LinearLayout {
private void update() {
switch (mChevronStyle) {
case AUTO:
case AssistantChevronStyle.NOT_SET_AUTOMATIC:
mChevronButton.setVisibility(
!mFixed && mExpandedView != null ? View.VISIBLE : View.GONE);
break;
case ALWAYS:
case AssistantChevronStyle.ALWAYS:
mChevronButton.setVisibility(View.VISIBLE);
break;
case NEVER:
case AssistantChevronStyle.NEVER:
mChevronButton.setVisibility(View.GONE);
break;
}
......
......@@ -14,10 +14,10 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import org.chromium.chrome.autofill_assistant.R;
import org.chromium.chrome.browser.autofill_assistant.AssistantChevronStyle;
import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
import org.chromium.chrome.browser.autofill_assistant.generic_ui.AssistantValue;
import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpander;
import org.chromium.chrome.browser.autofill_assistant.user_data.AssistantVerticalExpander.ChevronStyle;
import org.chromium.content.browser.input.PopupItemType;
import org.chromium.content.browser.input.SelectPopupDialog;
import org.chromium.content.browser.input.SelectPopupItem;
......@@ -126,7 +126,7 @@ public class AssistantPopupListSection implements AssistantAdditionalSection {
mSectionExpander.findViewById(R.id.section_title_add_button).setVisibility(View.GONE);
mSectionExpander.setFixed(true);
mSectionExpander.setChevronStyle(ChevronStyle.ALWAYS);
mSectionExpander.setChevronStyle(AssistantChevronStyle.ALWAYS);
parent.addView(mSectionExpander, index,
new ViewGroup.LayoutParams(
......
......@@ -104,6 +104,8 @@ import org.chromium.chrome.browser.autofill_assistant.proto.UserActionList;
import org.chromium.chrome.browser.autofill_assistant.proto.UserActionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ValueComparisonProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ValueProto;
import org.chromium.chrome.browser.autofill_assistant.proto.VerticalExpanderAccordionProto;
import org.chromium.chrome.browser.autofill_assistant.proto.VerticalExpanderViewProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ViewAttributesProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ViewContainerProto;
import org.chromium.chrome.browser.autofill_assistant.proto.ViewLayoutParamsProto;
......@@ -1696,4 +1698,115 @@ public class AutofillAssistantGenericUiTest {
BooleanList.newBuilder().addValues(true)))
.build()));
}
/**
* Creates three vertical expanders inside an accordion and tests expand/collapse functionality.
*/
@Test
@MediumTest
public void testVerticalExpanders() {
// Regular expander, can expand and collapse.
ViewProto expanderA =
(ViewProto) ViewProto.newBuilder()
.setVerticalExpanderView(
VerticalExpanderViewProto.newBuilder()
.setTitleView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander A Title")))
.setCollapsedView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander A Collapsed")))
.setExpandedView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander A Expanded"))))
.build();
// Only title+collapsed, can not expand (similar to date/time sections in current
// CollectUserData action).
ViewProto expanderB =
(ViewProto) ViewProto.newBuilder()
.setVerticalExpanderView(
VerticalExpanderViewProto.newBuilder()
.setTitleView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander B Title")))
.setCollapsedView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander B Collapsed")))
.setChevronStyle(
VerticalExpanderViewProto.ChevronStyle.ALWAYS))
.build();
// Regular expander, can expand and collapse.
ViewProto expanderC =
(ViewProto) ViewProto.newBuilder()
.setVerticalExpanderView(
VerticalExpanderViewProto.newBuilder()
.setTitleView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander C Title")))
.setCollapsedView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander C Collapsed")))
.setExpandedView(ViewProto.newBuilder().setTextView(
TextViewProto.newBuilder().setText(
"Expander C Expanded"))))
.build();
GenericUserInterfaceProto genericUserInterface =
(GenericUserInterfaceProto) GenericUserInterfaceProto.newBuilder()
.setRootView(ViewProto.newBuilder().setViewContainer(
ViewContainerProto.newBuilder()
.setExpanderAccordion(
VerticalExpanderAccordionProto.newBuilder()
.setOrientation(
LinearLayoutProto.Orientation
.VERTICAL))
.addViews(expanderA)
.addViews(expanderB)
.addViews(expanderC)))
.build();
ArrayList<ActionProto> list = new ArrayList<>();
list.add((ActionProto) ActionProto.newBuilder()
.setShowGenericUi(ShowGenericUiProto.newBuilder().setGenericUserInterface(
genericUserInterface))
.build());
AutofillAssistantTestScript script = new AutofillAssistantTestScript(
(SupportedScriptProto) SupportedScriptProto.newBuilder()
.setPath("form_target_website.html")
.setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip(
ChipProto.newBuilder().setText("Autostart")))
.build(),
list);
AutofillAssistantTestService testService =
new AutofillAssistantTestService(Collections.singletonList(script));
startAutofillAssistant(mTestRule.getActivity(), testService);
waitUntilViewMatchesCondition(withText("Expander A Title"), isDisplayed());
onView(withText("Expander A Title")).check(matches(isDisplayed()));
onView(withText("Expander B Title")).check(matches(isDisplayed()));
onView(withText("Expander C Title")).check(matches(isDisplayed()));
onView(withText("Expander A Collapsed")).check(matches(isDisplayed()));
onView(withText("Expander B Collapsed")).check(matches(isDisplayed()));
onView(withText("Expander C Collapsed")).check(matches(isDisplayed()));
onView(withText("Expander A Expanded")).check(matches(not(isDisplayed())));
onView(withText("Expander C Expanded")).check(matches(not(isDisplayed())));
onView(withText("Expander A Title")).perform(click());
waitUntilViewMatchesCondition(withText("Expander A Expanded"), isDisplayed());
onView(withText("Expander C Expanded")).check(matches(not(isDisplayed())));
onView(withText("Expander C Title")).perform(click());
waitUntilViewMatchesCondition(withText("Expander C Expanded"), isDisplayed());
waitUntilViewMatchesCondition(withText("Expander A Expanded"), not(isDisplayed()));
onView(withText("Expander C Title")).perform(click());
waitUntilViewMatchesCondition(withText("Expander C Expanded"), not(isDisplayed()));
onView(withText("Expander A Expanded")).check(matches(not(isDisplayed())));
}
}
......@@ -10,12 +10,21 @@
#include "chrome/browser/android/autofill_assistant/interaction_handler_android.h"
#include "chrome/browser/android/autofill_assistant/ui_controller_android_utils.h"
#include "components/autofill_assistant/browser/event_handler.h"
#include "components/autofill_assistant/browser/generic_ui_java_generated_enums.h"
#include "components/autofill_assistant/browser/ui_delegate.h"
namespace autofill_assistant {
namespace {
// Forward declaration to allow recursive calls.
base::android::ScopedJavaGlobalRef<jobject> CreateJavaView(
JNIEnv* env,
const base::android::ScopedJavaLocalRef<jobject>& jcontext,
const base::android::ScopedJavaGlobalRef<jobject>& jdelegate,
const ViewProto& proto,
std::map<std::string, base::android::ScopedJavaGlobalRef<jobject>>* views);
base::android::ScopedJavaLocalRef<jobject> CreateJavaDrawable(
JNIEnv* env,
const base::android::ScopedJavaLocalRef<jobject>& jcontext,
......@@ -84,6 +93,10 @@ base::android::ScopedJavaLocalRef<jobject> CreateJavaViewContainer(
jcontainer = Java_AssistantViewFactory_createLinearLayout(
env, jcontext, jidentifier, proto.linear_layout().orientation());
break;
case ViewContainerProto::kExpanderAccordion:
jcontainer = Java_AssistantViewFactory_createVerticalExpanderAccordion(
env, jcontext, jidentifier, proto.expander_accordion().orientation());
break;
case ViewContainerProto::CONTAINER_NOT_SET:
return nullptr;
}
......@@ -107,13 +120,56 @@ base::android::ScopedJavaLocalRef<jobject> CreateJavaTextView(
jtext_appearance);
}
// Forward declaration to allow recursive calls.
base::android::ScopedJavaGlobalRef<jobject> CreateJavaView(
base::android::ScopedJavaLocalRef<jobject> CreateJavaVerticalExpander(
JNIEnv* env,
const base::android::ScopedJavaLocalRef<jobject>& jcontext,
const base::android::ScopedJavaGlobalRef<jobject>& jdelegate,
const ViewProto& proto,
std::map<std::string, base::android::ScopedJavaGlobalRef<jobject>>* views);
const base::android::ScopedJavaLocalRef<jstring>& jidentifier,
const VerticalExpanderViewProto& proto,
std::map<std::string, base::android::ScopedJavaGlobalRef<jobject>>* views) {
base::android::ScopedJavaGlobalRef<jobject> jtitle_view = nullptr;
if (proto.has_title_view()) {
jtitle_view =
CreateJavaView(env, jcontext, jdelegate, proto.title_view(), views);
if (!jtitle_view) {
return nullptr;
}
}
base::android::ScopedJavaGlobalRef<jobject> jcollapsed_view = nullptr;
if (proto.has_collapsed_view()) {
jcollapsed_view =
CreateJavaView(env, jcontext, jdelegate, proto.collapsed_view(), views);
if (!jcollapsed_view) {
return nullptr;
}
}
base::android::ScopedJavaGlobalRef<jobject> jexpanded_view = nullptr;
if (proto.has_expanded_view()) {
jexpanded_view =
CreateJavaView(env, jcontext, jdelegate, proto.expanded_view(), views);
if (!jexpanded_view) {
return nullptr;
}
}
VerticalExpanderChevronStyle chevron_style;
switch (proto.chevron_style()) {
case VerticalExpanderViewProto::NOT_SET_AUTOMATIC:
chevron_style = VerticalExpanderChevronStyle::NOT_SET_AUTOMATIC;
break;
case VerticalExpanderViewProto::ALWAYS:
chevron_style = VerticalExpanderChevronStyle::ALWAYS;
break;
case VerticalExpanderViewProto::NEVER:
chevron_style = VerticalExpanderChevronStyle::NEVER;
break;
default:
NOTREACHED();
return nullptr;
}
return Java_AssistantViewFactory_createVerticalExpander(
env, jcontext, jidentifier, jtitle_view, jcollapsed_view, jexpanded_view,
static_cast<int>(chevron_style));
}
base::android::ScopedJavaGlobalRef<jobject> CreateJavaView(
JNIEnv* env,
......@@ -148,6 +204,11 @@ base::android::ScopedJavaGlobalRef<jobject> CreateJavaView(
jidentifier, jimage);
break;
}
case ViewProto::kVerticalExpanderView: {
jview = CreateJavaVerticalExpander(env, jcontext, jdelegate, jidentifier,
proto.vertical_expander_view(), views);
break;
}
case ViewProto::kTextInputView:
jview = Java_AssistantViewFactory_createTextInputView(
env, jcontext, jdelegate, jidentifier,
......
......@@ -108,6 +108,7 @@ jumbo_static_library("browser") {
"event_handler.h",
"features.cc",
"features.h",
"generic_ui_java_generated_enums.h",
"info_box.cc",
"info_box.h",
"metrics.cc",
......@@ -303,6 +304,7 @@ if (is_android) {
java_cpp_enum("autofill_assistant_enums_java") {
sources = [
"generic_ui_java_generated_enums.h",
"metrics.h",
"overlay_state.h",
"user_data.h",
......
// Copyright 2020 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.
#ifndef COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_GENERIC_UI_JAVA_GENERATED_ENUMS_H_
#define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_GENERIC_UI_JAVA_GENERATED_ENUMS_H_
#include "components/autofill_assistant/browser/service.pb.h"
#include "components/autofill_assistant/browser/view_layout.pb.h"
namespace autofill_assistant {
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.autofill_assistant)
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: AssistantChevronStyle
enum class VerticalExpanderChevronStyle {
NOT_SET_AUTOMATIC = 0,
ALWAYS = 1,
NEVER = 2,
};
} // namespace autofill_assistant
#endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_GENERIC_UI_JAVA_GENERATED_ENUMS_H_
......@@ -30,6 +30,8 @@ message ViewProto {
ImageViewProto image_view = 7;
// A text input view.
TextInputViewProto text_input_view = 8;
// A vertical expander with fixed title, collapsed, and expanded sections.
VerticalExpanderViewProto vertical_expander_view = 9;
}
}
......@@ -143,7 +145,10 @@ message ViewContainerProto {
// The list of views to add to this container.
repeated ViewProto views = 1;
oneof container { LinearLayoutProto linear_layout = 2; }
oneof container {
LinearLayoutProto linear_layout = 2;
VerticalExpanderAccordionProto expander_accordion = 3;
}
}
message LinearLayoutProto {
......@@ -155,6 +160,38 @@ message LinearLayoutProto {
optional Orientation orientation = 1;
}
// A vertical expander is a special type of vertical linear layout. It has two
// expansion states (expanded vs. collapsed) and toggles between them by tapping
// the title widget. For user guidance, a chevron is shown in the title to
// indicate the current state.
message VerticalExpanderViewProto {
enum ChevronStyle {
// Automatic: will show the chevron only if |expanded_view| is set.
NOT_SET_AUTOMATIC = 0;
ALWAYS = 1;
NEVER = 2;
}
// The view to show in the expander title.
optional ViewProto title_view = 1;
// The view to show in the collapsed state.
optional ViewProto collapsed_view = 2;
// The view to show in the expanded state.
optional ViewProto expanded_view = 3;
// The chevron style controls when to show the expand/collapse chevron.
optional ChevronStyle chevron_style = 4;
}
// This is a special type of linear layout that implements accordion-like
// functionality for all child vertical expanders, i.e., it ensures that at
// most one child vertical expander is expanded at any time.
message VerticalExpanderAccordionProto {
optional LinearLayoutProto.Orientation orientation = 2;
}
message TextViewProto {
optional string text = 1;
optional string text_appearance = 2;
......
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