summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
author Joshua Trask <joshtrask@google.com> 2023-10-05 19:43:40 +0000
committer Joshua Trask <joshtrask@google.com> 2023-10-05 20:50:41 +0000
commit677a65d143ddf42de7bcab28100421bf5bbcd593 (patch)
tree2f2ff8567f3de38149177cadb57a0c05e85d404e /java/src
parentc2f1d0cc70ef6083fd47e055a421fd74f620ea33 (diff)
`showEmptyState()` -> EmptyStateUiHelper
As part of ongoing work to pull low-level empty state responsibilities out of the pager adapter, this CL generally replicates the change prototyped in ag/24516421/5..7, in smaller incremental steps to "show the work." As originally described in that CL: "... moves most of the low-level logic of `showEmptyState()` into the UI helper. (...) also has the UI helper take responsibility for setting the visibility of the main "list view" in sync (opposite of) the empty state visibility." As presented in this CL, the "incremental steps" per-snapshot are: 1. Extract most of the implementation directly to the new method at `EmptyStateUiHelper.showEmptyState()`. The general functionality is covered by existing integration tests (e.g., commenting-out the new method body causes `UnbundledChooserActivityWorkProfileTest` to fail). New `EmptyStateUiHelper` unit tests cover finer points of the empty-state "button" conditions, and I've added a TODO comment at one place legacy behavior seemingly may not align with the original developer intent. 2. Also make the UI helper responsible for propagating empty-state visibility changes back to the main list view (hiding the main list when we show an empty state, and restoring it when the empty state is hidden). 3. Look up all the sub-views during `EmptyStateUiHelper` construction so we don't have to keep repeating their View IDs throughout. 4. Tighten visibility on `EmptyStateUiHelper.resetViewVisibilities()` now that it's a private `showEmptyState()` implementation detail (updated to package-protected/visible-for-testing). Also move the method to the end of the class (after all the public methods). Bug: 302311217 Test: IntentResolverUnitTests Change-Id: Iac0cf3d62e2c3bf22afa6a2796ae4e731b706c02
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java51
-rw-r--r--java/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelper.java118
2 files changed, 96 insertions, 73 deletions
diff --git a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
index ad9614b9..391cce7a 100644
--- a/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
+++ b/java/src/com/android/intentresolver/v2/MultiProfilePagerAdapter.java
@@ -21,8 +21,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.TextView;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;
@@ -414,6 +412,8 @@ public class MultiProfilePagerAdapter<
* The intention is to prevent the user from having to turn
* the work profile on if there will not be any apps resolved
* anyway.
+ *
+ * TODO: move this comment to the place where we configure our composite provider.
*/
public void showEmptyResolverListEmptyState(ListAdapterT listAdapter) {
final EmptyState emptyState = mEmptyStateProvider.getEmptyState(listAdapter);
@@ -449,48 +449,13 @@ public class MultiProfilePagerAdapter<
}
}
- protected void showEmptyState(
+ private void showEmptyState(
ListAdapterT activeListAdapter,
EmptyState emptyState,
View.OnClickListener buttonOnClick) {
ProfileDescriptor<PageViewT, SinglePageAdapterT> descriptor = getItem(
userHandleToPageIndex(activeListAdapter.getUserHandle()));
- descriptor.mRootView.findViewById(
- com.android.internal.R.id.resolver_list).setVisibility(View.GONE);
- descriptor.mEmptyStateUi.resetViewVisibilities();
- descriptor.setupContainerPadding();
-
- ViewGroup emptyStateView = descriptor.getEmptyStateView();
-
-
- TextView titleView = emptyStateView.findViewById(
- com.android.internal.R.id.resolver_empty_state_title);
- String title = emptyState.getTitle();
- if (title != null) {
- titleView.setVisibility(View.VISIBLE);
- titleView.setText(title);
- } else {
- titleView.setVisibility(View.GONE);
- }
-
- TextView subtitleView = emptyStateView.findViewById(
- com.android.internal.R.id.resolver_empty_state_subtitle);
- String subtitle = emptyState.getSubtitle();
- if (subtitle != null) {
- subtitleView.setVisibility(View.VISIBLE);
- subtitleView.setText(subtitle);
- } else {
- subtitleView.setVisibility(View.GONE);
- }
-
- View defaultEmptyText = emptyStateView.findViewById(com.android.internal.R.id.empty);
- defaultEmptyText.setVisibility(emptyState.useDefaultEmptyView() ? View.VISIBLE : View.GONE);
-
- Button button = emptyStateView.findViewById(
- com.android.internal.R.id.resolver_empty_state_button);
- button.setVisibility(buttonOnClick != null ? View.VISIBLE : View.GONE);
- button.setOnClickListener(buttonOnClick);
-
+ descriptor.mEmptyStateUi.showEmptyState(emptyState, buttonOnClick);
activeListAdapter.markTabLoaded();
}
@@ -505,8 +470,6 @@ public class MultiProfilePagerAdapter<
public void showListView(ListAdapterT activeListAdapter) {
ProfileDescriptor<PageViewT, SinglePageAdapterT> descriptor = getItem(
userHandleToPageIndex(activeListAdapter.getUserHandle()));
- descriptor.mRootView.findViewById(
- com.android.internal.R.id.resolver_list).setVisibility(View.VISIBLE);
descriptor.mEmptyStateUi.hide();
}
@@ -538,8 +501,10 @@ public class MultiProfilePagerAdapter<
mAdapter = adapter;
mEmptyStateView = rootView.findViewById(com.android.internal.R.id.resolver_empty_state);
mView = (PageViewT) rootView.findViewById(com.android.internal.R.id.resolver_list);
- mEmptyStateUi =
- new EmptyStateUiHelper(rootView, containerBottomPaddingOverrideSupplier);
+ mEmptyStateUi = new EmptyStateUiHelper(
+ rootView,
+ com.android.internal.R.id.resolver_list,
+ containerBottomPaddingOverrideSupplier);
}
protected ViewGroup getEmptyStateView() {
diff --git a/java/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelper.java b/java/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelper.java
index fc852f5c..2f1e1b59 100644
--- a/java/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelper.java
+++ b/java/src/com/android/intentresolver/v2/emptystate/EmptyStateUiHelper.java
@@ -17,6 +17,11 @@ package com.android.intentresolver.v2.emptystate;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.intentresolver.emptystate.EmptyState;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.Optional;
import java.util.function.Supplier;
@@ -26,58 +31,111 @@ import java.util.function.Supplier;
* some empty-state status.
*/
public class EmptyStateUiHelper {
- private final View mEmptyStateView;
private final Supplier<Optional<Integer>> mContainerBottomPaddingOverrideSupplier;
+ private final View mEmptyStateView;
+ private final View mListView;
+ private final View mEmptyStateContainerView;
+ private final TextView mEmptyStateTitleView;
+ private final TextView mEmptyStateSubtitleView;
+ private final Button mEmptyStateButtonView;
+ private final View mEmptyStateProgressView;
+ private final View mEmptyStateEmptyView;
public EmptyStateUiHelper(
ViewGroup rootView,
+ int listViewResourceId,
Supplier<Optional<Integer>> containerBottomPaddingOverrideSupplier) {
+ mContainerBottomPaddingOverrideSupplier = containerBottomPaddingOverrideSupplier;
mEmptyStateView =
rootView.requireViewById(com.android.internal.R.id.resolver_empty_state);
- mContainerBottomPaddingOverrideSupplier = containerBottomPaddingOverrideSupplier;
+ mListView = rootView.requireViewById(listViewResourceId);
+ mEmptyStateContainerView = mEmptyStateView.requireViewById(
+ com.android.internal.R.id.resolver_empty_state_container);
+ mEmptyStateTitleView = mEmptyStateView.requireViewById(
+ com.android.internal.R.id.resolver_empty_state_title);
+ mEmptyStateSubtitleView = mEmptyStateView.requireViewById(
+ com.android.internal.R.id.resolver_empty_state_subtitle);
+ mEmptyStateButtonView = mEmptyStateView.requireViewById(
+ com.android.internal.R.id.resolver_empty_state_button);
+ mEmptyStateProgressView = mEmptyStateView.requireViewById(
+ com.android.internal.R.id.resolver_empty_state_progress);
+ mEmptyStateEmptyView = mEmptyStateView.requireViewById(com.android.internal.R.id.empty);
+ }
+
+ /**
+ * Display the described empty state.
+ * @param emptyState the data describing the cause of this empty-state condition.
+ * @param buttonOnClick handler for a button that the user might be able to use to circumvent
+ * the empty-state condition. If null, no button will be displayed.
+ */
+ public void showEmptyState(EmptyState emptyState, View.OnClickListener buttonOnClick) {
+ resetViewVisibilities();
+ setupContainerPadding();
+
+ String title = emptyState.getTitle();
+ if (title != null) {
+ mEmptyStateTitleView.setVisibility(View.VISIBLE);
+ mEmptyStateTitleView.setText(title);
+ } else {
+ mEmptyStateTitleView.setVisibility(View.GONE);
+ }
+
+ String subtitle = emptyState.getSubtitle();
+ if (subtitle != null) {
+ mEmptyStateSubtitleView.setVisibility(View.VISIBLE);
+ mEmptyStateSubtitleView.setText(subtitle);
+ } else {
+ mEmptyStateSubtitleView.setVisibility(View.GONE);
+ }
+
+ mEmptyStateEmptyView.setVisibility(
+ emptyState.useDefaultEmptyView() ? View.VISIBLE : View.GONE);
+ // TODO: The EmptyState API says that if `useDefaultEmptyView()` is true, we'll ignore the
+ // state's specified title/subtitle; where (if anywhere) is that implemented?
+
+ mEmptyStateButtonView.setVisibility(buttonOnClick != null ? View.VISIBLE : View.GONE);
+ mEmptyStateButtonView.setOnClickListener(buttonOnClick);
+
+ // Don't show the main list view when we're showing an empty state.
+ mListView.setVisibility(View.GONE);
}
/** Sets up the padding of the view containing the empty state screens. */
public void setupContainerPadding() {
- View container = mEmptyStateView.requireViewById(
- com.android.internal.R.id.resolver_empty_state_container);
Optional<Integer> bottomPaddingOverride = mContainerBottomPaddingOverrideSupplier.get();
bottomPaddingOverride.ifPresent(paddingBottom ->
- container.setPadding(
- container.getPaddingLeft(),
- container.getPaddingTop(),
- container.getPaddingRight(),
+ mEmptyStateContainerView.setPadding(
+ mEmptyStateContainerView.getPaddingLeft(),
+ mEmptyStateContainerView.getPaddingTop(),
+ mEmptyStateContainerView.getPaddingRight(),
paddingBottom));
}
- public void resetViewVisibilities() {
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_title)
- .setVisibility(View.VISIBLE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_subtitle)
- .setVisibility(View.VISIBLE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_button)
- .setVisibility(View.INVISIBLE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_progress)
- .setVisibility(View.GONE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.empty)
- .setVisibility(View.GONE);
- mEmptyStateView.setVisibility(View.VISIBLE);
- }
-
public void showSpinner() {
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_title)
- .setVisibility(View.INVISIBLE);
+ mEmptyStateTitleView.setVisibility(View.INVISIBLE);
// TODO: subtitle?
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_button)
- .setVisibility(View.INVISIBLE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.resolver_empty_state_progress)
- .setVisibility(View.VISIBLE);
- mEmptyStateView.requireViewById(com.android.internal.R.id.empty)
- .setVisibility(View.GONE);
+ mEmptyStateButtonView.setVisibility(View.INVISIBLE);
+ mEmptyStateProgressView.setVisibility(View.VISIBLE);
+ mEmptyStateEmptyView.setVisibility(View.GONE);
}
public void hide() {
mEmptyStateView.setVisibility(View.GONE);
+ mListView.setVisibility(View.VISIBLE);
+ }
+
+ // TODO: this is exposed for testing so we can thoroughly prepare initial conditions that let us
+ // observe the resulting change. In reality it's only invoked as part of `showEmptyState()` and
+ // we could consider setting up narrower "realistic" preconditions to make assertions about the
+ // higher-level operation.
+ @VisibleForTesting
+ void resetViewVisibilities() {
+ mEmptyStateTitleView.setVisibility(View.VISIBLE);
+ mEmptyStateSubtitleView.setVisibility(View.VISIBLE);
+ mEmptyStateButtonView.setVisibility(View.INVISIBLE);
+ mEmptyStateProgressView.setVisibility(View.GONE);
+ mEmptyStateEmptyView.setVisibility(View.GONE);
+ mEmptyStateView.setVisibility(View.VISIBLE);
}
}