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

Commit 5a82092b authored by Harsh Lal's avatar Harsh Lal Committed by Automerger Merge Worker
Browse files

Merge "Add fallback screen logic to CredentialSelectorActivity" into udc-dev...

Merge "Add fallback screen logic to CredentialSelectorActivity" into udc-dev am: 80420d7e am: d27508c4

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22254451



Change-Id: I3aed8463bef517dd459bdfff12ea304f84ec3dbf
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 3dd2dd99 d27508c4
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -103,6 +103,8 @@
  <string name="get_dialog_title_use_sign_in_for">Use your saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <string name="get_dialog_title_use_sign_in_for">Use your saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
  <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
  <string name="get_dialog_title_choose_sign_in_for">Choose a saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
  <string name="get_dialog_title_choose_sign_in_for">Choose a saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
  <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
  <string name="get_dialog_title_choose_option_for">Choose an option for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
  <!-- This is a label for a button that links the user to different sign-in methods . [CHAR LIMIT=80] -->
  <!-- This is a label for a button that links the user to different sign-in methods . [CHAR LIMIT=80] -->
  <string name="get_dialog_use_saved_passkey_for">Sign in another way</string>
  <string name="get_dialog_use_saved_passkey_for">Sign in another way</string>
  <!-- This is a label for a button that links the user to different sign-in methods. [CHAR LIMIT=80] -->
  <!-- This is a label for a button that links the user to different sign-in methods. [CHAR LIMIT=80] -->
+122 −2
Original line number Original line Diff line number Diff line
@@ -19,8 +19,31 @@ package com.android.credentialmanager.getflow
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResult
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.IntentSenderRequest
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
import com.android.compose.rememberSystemUiController
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.CredentialSelectorViewModel
import com.android.credentialmanager.R
import com.android.credentialmanager.common.BaseEntry
import com.android.credentialmanager.common.ProviderActivityState
import com.android.credentialmanager.common.ui.CredentialContainerCard
import com.android.credentialmanager.common.ui.HeadlineIcon
import com.android.credentialmanager.common.ui.HeadlineText
import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
import com.android.credentialmanager.common.ui.ModalBottomSheet
import com.android.credentialmanager.common.ui.SheetContainerCard
import com.android.credentialmanager.common.ui.setBottomSheetSystemBarsColor
import com.android.credentialmanager.logging.GetCredentialEvent
import com.android.internal.logging.UiEventLogger



@Composable
@Composable
fun GetGenericCredentialScreen(
fun GetGenericCredentialScreen(
@@ -28,5 +51,102 @@ fun GetGenericCredentialScreen(
        getCredentialUiState: GetCredentialUiState,
        getCredentialUiState: GetCredentialUiState,
        providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
        providerActivityLauncher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>
) {
) {
    // TODO(b/274129098): Implement Screen for mDocs
    val sysUiController = rememberSystemUiController()
    setBottomSheetSystemBarsColor(sysUiController)
    ModalBottomSheet(
        sheetContent = {
            when (viewModel.uiState.providerActivityState) {
                ProviderActivityState.NOT_APPLICABLE -> {
                    PrimarySelectionCardGeneric(
                            requestDisplayInfo = getCredentialUiState.requestDisplayInfo,
                            providerDisplayInfo = getCredentialUiState.providerDisplayInfo,
                            providerInfoList = getCredentialUiState.providerInfoList,
                            onEntrySelected = viewModel::getFlowOnEntrySelected,
                            onLog = { viewModel.logUiEvent(it) },
                    )
                    viewModel.uiMetrics.log(GetCredentialEvent
                            .CREDMAN_GET_CRED_SCREEN_PRIMARY_SELECTION)
                }
                ProviderActivityState.READY_TO_LAUNCH -> {
                    // Launch only once per providerActivityState change so that the provider
                    // UI will not be accidentally launched twice.
                    LaunchedEffect(viewModel.uiState.providerActivityState) {
                        viewModel.launchProviderUi(providerActivityLauncher)
                    }
                    viewModel.uiMetrics.log(GetCredentialEvent
                            .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_READY_TO_LAUNCH)
                }
                ProviderActivityState.PENDING -> {
                    // Hide our content when the provider activity is active.
                    viewModel.uiMetrics.log(GetCredentialEvent
                            .CREDMAN_GET_CRED_PROVIDER_ACTIVITY_PENDING)
                }
            }
        },
        onDismiss = viewModel::onUserCancel,
    )
}

@Composable
fun PrimarySelectionCardGeneric(
        requestDisplayInfo: RequestDisplayInfo,
        providerDisplayInfo: ProviderDisplayInfo,
        providerInfoList: List<ProviderInfo>,
        onEntrySelected: (BaseEntry) -> Unit,
        onLog: @Composable (UiEventLogger.UiEventEnum) -> Unit,
) {
    val sortedUserNameToCredentialEntryList =
            providerDisplayInfo.sortedUserNameToCredentialEntryList
    SheetContainerCard {
        // When only one provider (not counting the remote-only provider) exists, display that
        // provider's icon + name up top.
        if (providerInfoList.size <= 2) { // It's only possible to be the single provider case
            // if we are started with no more than 2 providers.
            val nonRemoteProviderList = providerInfoList.filter(
                { it.credentialEntryList.isNotEmpty() || it.authenticationEntryList.isNotEmpty() }
            )
            if (nonRemoteProviderList.size == 1) {
                val providerInfo = nonRemoteProviderList.firstOrNull() // First should always work
                // but just to be safe.
                if (providerInfo != null) {
                    item {
                        HeadlineIcon(
                                bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
                                tint = Color.Unspecified,
                        )
                    }
                    item { Divider(thickness = 4.dp, color = Color.Transparent) }
                    item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
                    item { Divider(thickness = 16.dp, color = Color.Transparent) }
                }
            }
        }

        item {
            HeadlineText(
                    text = stringResource(
                            R.string.get_dialog_title_choose_option_for,
                            requestDisplayInfo.appName
                    ),
            )
        }
        item { Divider(thickness = 24.dp, color = Color.Transparent) }
        item {
            CredentialContainerCard {
                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
                    // Show max 4 entries in this primary page
                    sortedUserNameToCredentialEntryList.forEach {
                        // TODO(b/275375861): fallback UI merges entries by account names.
                        //  Need a strategy to be able to show all entries.
                        CredentialEntryRow(
                                credentialEntryInfo = it.sortedCredentialEntryList.first(),
                                onEntrySelected = onEntrySelected,
                                enforceOneLine = true,
                        )
                    }
                }
            }
        }
    }
    onLog(GetCredentialEvent.CREDMAN_GET_CRED_PRIMARY_SELECTION_CARD)
}
}