Make wallet screen scrollable in landscape mode.
Also added test cases for cards with bad informations to prevent crash; change the wallet tile label to use the one fetched from QAW API, with a fallback static string in SysUI. see demo: https://drive.google.com/file/d/1Pu39KJTbQNJ2ABV__fVfdnNu9V_XlOsn/view?usp=sharing&resourcekey=0-WJgX6aUZTy9j3QWHfz3mjg Test: atest Test: manual Bug: 187970998 Change-Id: I5c073989a9db959eba324b693c04e46a0b96d6b2
This commit is contained in:
@@ -22,60 +22,67 @@
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false">
|
||||
<Toolbar
|
||||
android:id="@+id/action_bar"
|
||||
style="?android:attr/actionBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:navigationContentDescription="@null" />
|
||||
android:id="@+id/action_bar"
|
||||
style="?android:attr/actionBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:navigationContentDescription="@null" />
|
||||
<LinearLayout
|
||||
android:id="@+id/card_carousel_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="48dp"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/wallet_screen_header_view_size"
|
||||
android:layout_height="@dimen/wallet_screen_header_view_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@null"/>
|
||||
<TextView
|
||||
android:id="@+id/label"
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Wallet.TextAppearance"
|
||||
android:textAlignment="center"/>
|
||||
|
||||
<com.android.systemui.wallet.ui.WalletCardCarousel
|
||||
android:id="@+id/card_carousel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:transitionName="dotIndicator"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_marginVertical="24dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/wallet_action_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:paddingVertical="@dimen/wallet_button_vertical_padding"
|
||||
android:paddingHorizontal="@dimen/wallet_button_horizontal_padding"
|
||||
android:background="@drawable/wallet_action_button_bg"
|
||||
android:textColor="?androidprv:attr/textColorPrimaryInverse"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone"/>
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="@dimen/wallet_screen_header_view_size"
|
||||
android:layout_height="@dimen/wallet_screen_header_view_size"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="@null"/>
|
||||
<TextView
|
||||
android:id="@+id/label"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Wallet.TextAppearance"
|
||||
android:textAlignment="center"/>
|
||||
|
||||
<com.android.systemui.wallet.ui.WalletCardCarousel
|
||||
android:id="@+id/card_carousel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:transitionName="dotIndicator"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:layout_marginVertical="24dp"/>
|
||||
<Button
|
||||
android:id="@+id/wallet_action_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginVertical="16dp"
|
||||
android:paddingVertical="@dimen/wallet_button_vertical_padding"
|
||||
android:paddingHorizontal="@dimen/wallet_button_horizontal_padding"
|
||||
android:background="@drawable/wallet_action_button_bg"
|
||||
android:textColor="?androidprv:attr/textColorPrimaryInverse"
|
||||
android:textAlignment="center"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
android:layout_weight="0.1"/>
|
||||
<Button
|
||||
android:id="@+id/wallet_app_button"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -88,7 +95,6 @@
|
||||
android:textColor="?androidprv:attr/colorAccentPrimary"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginVertical="24dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/wallet_empty_state"/>
|
||||
|
||||
@@ -152,7 +152,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
||||
|
||||
@Override
|
||||
protected void handleUpdateState(State state, Object arg) {
|
||||
state.label = mLabel;
|
||||
CharSequence label = mQuickAccessWalletClient.getServiceLabel();
|
||||
state.label = label == null ? mLabel : label;
|
||||
state.contentDescription = state.label;
|
||||
state.icon = ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
|
||||
boolean isDeviceLocked = !mKeyguardStateController.isUnlocked();
|
||||
@@ -197,7 +198,8 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
||||
|
||||
@Override
|
||||
public CharSequence getTileLabel() {
|
||||
return mLabel;
|
||||
CharSequence label = mQuickAccessWalletClient.getServiceLabel();
|
||||
return label == null ? mLabel : label;
|
||||
}
|
||||
|
||||
private void queryWalletCards() {
|
||||
@@ -227,7 +229,9 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> {
|
||||
}
|
||||
int selectedIndex = response.getSelectedIndex();
|
||||
if (selectedIndex >= cards.size()) {
|
||||
Log.d(TAG, "Selected card index out of bounds.");
|
||||
Log.w(TAG, "Error retrieving cards: Invalid selected card index.");
|
||||
mSelectedCard = null;
|
||||
mCardViewDrawable = null;
|
||||
return;
|
||||
}
|
||||
mSelectedCard = cards.get(selectedIndex);
|
||||
|
||||
@@ -131,8 +131,14 @@ public class WalletScreenController implements
|
||||
if (data.isEmpty()) {
|
||||
showEmptyStateView();
|
||||
} else {
|
||||
mWalletView.showCardCarousel(
|
||||
data, response.getSelectedIndex(), !mKeyguardStateController.isUnlocked());
|
||||
int selectedIndex = response.getSelectedIndex();
|
||||
if (selectedIndex >= data.size()) {
|
||||
Log.w(TAG, "Invalid selected card index, showing empty state.");
|
||||
showEmptyStateView();
|
||||
} else {
|
||||
mWalletView.showCardCarousel(
|
||||
data, selectedIndex, !mKeyguardStateController.isUnlocked());
|
||||
}
|
||||
}
|
||||
removeMinHeightAndRecordHeightOnLayout();
|
||||
});
|
||||
|
||||
@@ -92,6 +92,7 @@ import java.util.Collections;
|
||||
public class QuickAccessWalletTileTest extends SysuiTestCase {
|
||||
|
||||
private static final String CARD_ID = "card_id";
|
||||
private static final String LABEL = "QAW";
|
||||
private static final Icon CARD_IMAGE =
|
||||
Icon.createWithBitmap(Bitmap.createBitmap(70, 50, Bitmap.Config.ARGB_8888));
|
||||
|
||||
@@ -141,6 +142,7 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
|
||||
when(mHost.getContext()).thenReturn(mSpiedContext);
|
||||
when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger);
|
||||
when(mFeatureFlags.isQuickAccessWalletEnabled()).thenReturn(true);
|
||||
when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
|
||||
when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
|
||||
when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
|
||||
|
||||
@@ -248,13 +250,19 @@ public class QuickAccessWalletTileTest extends SysuiTestCase {
|
||||
|
||||
mTile.handleUpdateState(state, null);
|
||||
|
||||
assertEquals(mContext.getString(R.string.wallet_title), state.label.toString());
|
||||
assertEquals(LABEL, state.label.toString());
|
||||
assertTrue(state.label.toString().contentEquals(state.contentDescription));
|
||||
assertEquals(icon, state.icon);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTileLabel() {
|
||||
public void testGetTileLabel_serviceLabelExists() {
|
||||
assertEquals(LABEL, mTile.getTileLabel().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTileLabel_serviceLabelDoesNotExist() {
|
||||
when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(null);
|
||||
assertEquals(mContext.getString(R.string.wallet_title), mTile.getTileLabel().toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -181,6 +181,80 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
||||
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryCards_hasCards_showCarousel_badCard_parseLabel_notCrash() {
|
||||
GetWalletCardsResponse response =
|
||||
new GetWalletCardsResponse(
|
||||
Collections.singletonList(createCrazyWalletCard(mContext, true)), 0);
|
||||
|
||||
mController.queryWalletCards();
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
|
||||
|
||||
QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
|
||||
mCallbackCaptor.getValue();
|
||||
|
||||
assertEquals(mController, callback);
|
||||
|
||||
callback.onWalletCardsRetrieved(response);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
|
||||
assertEquals("This\nis\ncrazy!!", mWalletView.getCardLabel().getText().toString());
|
||||
assertEquals(GONE, mWalletView.getActionButton().getVisibility());
|
||||
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryCards_hasCards_showCarousel_badCard_noLabel_notCrash() {
|
||||
GetWalletCardsResponse response =
|
||||
new GetWalletCardsResponse(
|
||||
Collections.singletonList(createCrazyWalletCard(mContext, false)), 0);
|
||||
|
||||
mController.queryWalletCards();
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
|
||||
|
||||
QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
|
||||
mCallbackCaptor.getValue();
|
||||
|
||||
assertEquals(mController, callback);
|
||||
|
||||
callback.onWalletCardsRetrieved(response);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
assertEquals(VISIBLE, mWalletView.getCardCarouselContainer().getVisibility());
|
||||
assertEquals("", mWalletView.getCardLabel().getText().toString());
|
||||
assertEquals(GONE, mWalletView.getActionButton().getVisibility());
|
||||
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryCards_hasCards_showCarousel_invalidSelectedIndex_notCrash() {
|
||||
GetWalletCardsResponse response =
|
||||
new GetWalletCardsResponse(
|
||||
Collections.singletonList(createCrazyWalletCard(mContext, true)), 8);
|
||||
|
||||
mController.queryWalletCards();
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
|
||||
|
||||
QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
|
||||
mCallbackCaptor.getValue();
|
||||
|
||||
assertEquals(mController, callback);
|
||||
|
||||
callback.onWalletCardsRetrieved(response);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
assertEquals(GONE, mWalletView.getCardCarouselContainer().getVisibility());
|
||||
assertEquals(VISIBLE, mWalletView.getEmptyStateView().getVisibility());
|
||||
assertEquals(GONE, mWalletView.getErrorView().getVisibility());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryCards_noCards_showEmptyState() {
|
||||
GetWalletCardsResponse response = new GetWalletCardsResponse(Collections.EMPTY_LIST, 0);
|
||||
@@ -329,6 +403,15 @@ public class WalletScreenControllerTest extends SysuiTestCase {
|
||||
.build();
|
||||
}
|
||||
|
||||
private WalletCard createCrazyWalletCard(Context context, boolean hasLabel) {
|
||||
PendingIntent pendingIntent =
|
||||
PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
return new WalletCard.Builder("BadCard", createIcon(), "•••• 1234", pendingIntent)
|
||||
.setCardIcon(null)
|
||||
.setCardLabel(hasLabel ? "This\nis\ncrazy!!" : null)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static Icon createIcon() {
|
||||
return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user