Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c3e8160 authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Change the back button to close button on more options page

This applies to both the single tap and the autofill-credman
feature. For the latter, we don't propagate the cancellation
exception back to the developer as the user can bring up the
selector again.

Bug: 328086145
Test: Cts

Change-Id: Ib30c49aabe64144c44676ba81535822f9a87889a
parent 4487bc7f
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -258,6 +258,15 @@ class CredentialSelectorViewModel(
        )
        )
    }
    }


    fun getFlowOnMoreOptionOnlySelected() {
        Log.d(Constants.LOG_TAG, "More Option Only selected")
        uiState = uiState.copy(
                getCredentialUiState = uiState.getCredentialUiState?.copy(
                        currentScreenState = GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY
                )
        )
    }

    fun getFlowOnMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
    fun getFlowOnMoreOptionOnSnackBarSelected(isNoAccount: Boolean) {
        Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
        Log.d(Constants.LOG_TAG, "More Option on snackBar selected")
        uiState = uiState.copy(
        uiState = uiState.copy(
+32 −0
Original line number Original line Diff line number Diff line
@@ -349,6 +349,38 @@ fun MoreOptionTopAppBar(
    }
    }
}
}


@Composable
fun MoreOptionTopAppBarWithCustomNavigation(
        text: String,
        onNavigationIconClicked: () -> Unit,
        navigationIcon: ImageVector,
        navigationIconContentDescription: String,
        bottomPadding: Dp,
) {
    Row(
            modifier = Modifier.padding(top = 12.dp, bottom = bottomPadding),
            verticalAlignment = Alignment.CenterVertically,
    ) {
        IconButton(
                modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp),
                onClick = onNavigationIconClicked
        ) {
            Box(
                    modifier = Modifier.size(48.dp),
                    contentAlignment = Alignment.Center,
            ) {
                Icon(
                        imageVector = navigationIcon,
                        contentDescription = navigationIconContentDescription,
                        modifier = Modifier.size(24.dp).autoMirrored(),
                        tint = LocalAndroidColorScheme.current.onSurfaceVariant,
                )
            }
        }
        LargeTitleText(text = text, modifier = Modifier.padding(horizontal = 4.dp))
    }
}

private fun Modifier.autoMirrored() = composed {
private fun Modifier.autoMirrored() = composed {
    when (LocalLayoutDirection.current) {
    when (LocalLayoutDirection.current) {
        LayoutDirection.Rtl -> graphicsLayer(scaleX = -1f)
        LayoutDirection.Rtl -> graphicsLayer(scaleX = -1f)
+42 −7
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.material.icons.outlined.QrCodeScanner
import androidx.compose.material3.Divider
import androidx.compose.material3.Divider
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextButton
@@ -69,6 +70,7 @@ import com.android.credentialmanager.common.ui.HeadlineText
import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
import com.android.credentialmanager.common.ui.ModalBottomSheet
import com.android.credentialmanager.common.ui.ModalBottomSheet
import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
import com.android.credentialmanager.common.ui.MoreOptionTopAppBarWithCustomNavigation
import com.android.credentialmanager.common.ui.SheetContainerCard
import com.android.credentialmanager.common.ui.SheetContainerCard
import com.android.credentialmanager.common.ui.Snackbar
import com.android.credentialmanager.common.ui.Snackbar
import com.android.credentialmanager.common.ui.SnackbarActionText
import com.android.credentialmanager.common.ui.SnackbarActionText
@@ -147,7 +149,7 @@ fun GetCredentialScreen(
                                .currentScreenState == GetScreenState.BIOMETRIC_SELECTION) {
                                .currentScreenState == GetScreenState.BIOMETRIC_SELECTION) {
                            BiometricSelectionPage(
                            BiometricSelectionPage(
                                biometricEntry = getCredentialUiState.activeEntry,
                                biometricEntry = getCredentialUiState.activeEntry,
                                onMoreOptionSelected = viewModel::getFlowOnMoreOptionSelected,
                                onMoreOptionSelected = viewModel::getFlowOnMoreOptionOnlySelected,
                                onCancelFlowAndFinish = viewModel::onUserCancel,
                                onCancelFlowAndFinish = viewModel::onUserCancel,
                                onIllegalStateAndFinish = viewModel::onIllegalUiState,
                                onIllegalStateAndFinish = viewModel::onIllegalUiState,
                                requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
                                requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
@@ -162,6 +164,28 @@ fun GetCredentialScreen(
                                onBiometricPromptStateChange =
                                onBiometricPromptStateChange =
                                viewModel::onBiometricPromptStateChange
                                viewModel::onBiometricPromptStateChange
                            )
                            )
                        } else if (credmanBiometricApiEnabled() &&
                                getCredentialUiState.currentScreenState
                                == GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY) {
                            AllSignInOptionCard(
                                    providerInfoList = getCredentialUiState.providerInfoList,
                                    providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
                                    onEntrySelected = viewModel::getFlowOnEntrySelected,
                                    onBackButtonClicked = viewModel::onUserCancel,
                                    onCancel = viewModel::onUserCancel,
                                    onLog = { viewModel.logUiEvent(it) },
                                    customTopBar = { MoreOptionTopAppBarWithCustomNavigation(
                                            text = stringResource(
                                                    R.string.get_dialog_title_sign_in_options),
                                            onNavigationIconClicked = viewModel::onUserCancel,
                                            navigationIcon = Icons.Filled.Close,
                                            navigationIconContentDescription =
                                            stringResource(R.string.accessibility_close_button),
                                            bottomPadding = 0.dp
                                    ) }
                            )
                            viewModel.uiMetrics.log(GetCredentialEvent
                                    .CREDMAN_GET_CRED_SCREEN_ALL_SIGN_IN_OPTIONS)
                        } else {
                        } else {
                            AllSignInOptionCard(
                            AllSignInOptionCard(
                                providerInfoList = getCredentialUiState.providerInfoList,
                                providerInfoList = getCredentialUiState.providerInfoList,
@@ -637,7 +661,13 @@ private fun findSingleProviderIdForPrimaryPage(
    return providerId
    return providerId
}
}


/** Draws the secondary credential selection page, where all sign-in options are listed. */
/**
 * Draws the secondary credential selection page, where all sign-in options are listed.
 *
 * By default, this card has 'back' navigation whereby user can navigate back to invoke
 * [onBackButtonClicked]. However if a different top bar with possibly a different navigation
 * is required, then the caller of this Composable can set a [customTopBar].
 */
@Composable
@Composable
fun AllSignInOptionCard(
fun AllSignInOptionCard(
    providerInfoList: List<ProviderInfo>,
    providerInfoList: List<ProviderInfo>,
@@ -646,16 +676,21 @@ fun AllSignInOptionCard(
    onBackButtonClicked: () -> Unit,
    onBackButtonClicked: () -> Unit,
    onCancel: () -> Unit,
    onCancel: () -> Unit,
    onLog: @Composable (UiEventEnum) -> Unit,
    onLog: @Composable (UiEventEnum) -> Unit,
    customTopBar: (@Composable() () -> Unit)? = null
) {
) {
    val sortedUserNameToCredentialEntryList =
    val sortedUserNameToCredentialEntryList =
        providerDisplayInfo.sortedUserNameToCredentialEntryList
        providerDisplayInfo.sortedUserNameToCredentialEntryList
    val authenticationEntryList = providerDisplayInfo.authenticationEntryList
    val authenticationEntryList = providerDisplayInfo.authenticationEntryList
    SheetContainerCard(topAppBar = {
    SheetContainerCard(topAppBar = {
        if (customTopBar != null) {
            customTopBar()
        } else {
            MoreOptionTopAppBar(
            MoreOptionTopAppBar(
                    text = stringResource(R.string.get_dialog_title_sign_in_options),
                    text = stringResource(R.string.get_dialog_title_sign_in_options),
                    onNavigationIconClicked = onBackButtonClicked,
                    onNavigationIconClicked = onBackButtonClicked,
                    bottomPadding = 0.dp,
                    bottomPadding = 0.dp,
            )
            )
        }
    }) {
    }) {
        var isFirstSection = true
        var isFirstSection = true
        // For username
        // For username
+14 −2
Original line number Original line Diff line number Diff line
@@ -163,7 +163,11 @@ enum class GetScreenState {
    /** The single tap biometric selection page. */
    /** The single tap biometric selection page. */
    BIOMETRIC_SELECTION,
    BIOMETRIC_SELECTION,


    /** The secondary credential selection page, where all sign-in options are listed. */
    /**
     * The secondary credential selection page, where all sign-in options are listed.
     *
     * This state is expected to go back to PRIMARY_SELECTION on back navigation
     */
    ALL_SIGN_IN_OPTIONS,
    ALL_SIGN_IN_OPTIONS,


    /** The snackbar only page when there's no account but only a remoteEntry. */
    /** The snackbar only page when there's no account but only a remoteEntry. */
@@ -171,6 +175,14 @@ enum class GetScreenState {


    /** The snackbar when there are only auth entries and all of them turn out to be empty. */
    /** The snackbar when there are only auth entries and all of them turn out to be empty. */
    UNLOCKED_AUTH_ENTRIES_ONLY,
    UNLOCKED_AUTH_ENTRIES_ONLY,

    /**
     * The secondary credential selection page, where all sign-in options are listed.
     *
     * This state has no option for the user to navigate back to PRIMARY_SELECTION, and
     * instead can be terminated independently.
     */
    ALL_SIGN_IN_OPTIONS_ONLY,
}
}




@@ -285,7 +297,7 @@ private fun toGetScreenState(
        providerDisplayInfo.remoteEntry != null)
        providerDisplayInfo.remoteEntry != null)
        GetScreenState.REMOTE_ONLY
        GetScreenState.REMOTE_ONLY
    else if (isRequestForAllOptions)
    else if (isRequestForAllOptions)
        GetScreenState.ALL_SIGN_IN_OPTIONS
        GetScreenState.ALL_SIGN_IN_OPTIONS_ONLY
    else if (isBiometricFlow(providerDisplayInfo, isFlowAutoSelectable(providerDisplayInfo)))
    else if (isBiometricFlow(providerDisplayInfo, isFlowAutoSelectable(providerDisplayInfo)))
        GetScreenState.BIOMETRIC_SELECTION
        GetScreenState.BIOMETRIC_SELECTION
    else GetScreenState.PRIMARY_SELECTION
    else GetScreenState.PRIMARY_SELECTION
+5 −3
Original line number Original line Diff line number Diff line
@@ -5188,11 +5188,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    String[] exception =  resultData.getStringArray(
                    String[] exception =  resultData.getStringArray(
                            CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION);
                            CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION);
                    if (exception != null && exception.length >= 2) {
                    if (exception != null && exception.length >= 2) {
                        String errType = exception[0];
                        String errMsg = exception[1];
                        Slog.w(TAG, "Credman bottom sheet from pinned "
                        Slog.w(TAG, "Credman bottom sheet from pinned "
                                + "entry failed with: + " + exception[0] + " , "
                                + "entry failed with: + " + errType + " , "
                                + exception[1]);
                                + errMsg);
                        sendCredentialManagerResponseToApp(/*response=*/ null,
                        sendCredentialManagerResponseToApp(/*response=*/ null,
                                new GetCredentialException(exception[0], exception[1]),
                                new GetCredentialException(errType, errMsg),
                                mAutofillId);
                                mAutofillId);
                    }
                    }
                } else {
                } else {
Loading