Multi credential flattened screen changes

Bug: 310986916
Test: Manual. See go/credential-selector-ui
Change-Id: If91f1792dec5357075e11a9c5d866a661c5310dd
diff --git a/packages/CredentialManager/wear/res/values/strings.xml b/packages/CredentialManager/wear/res/values/strings.xml
index 4a92936..80b1b30 100644
--- a/packages/CredentialManager/wear/res/values/strings.xml
+++ b/packages/CredentialManager/wear/res/values/strings.xml
@@ -33,6 +33,8 @@
   <string name="dialog_continue_button">Continue</string>
   <!-- Content description for the sign in options button of a screen. [CHAR LIMIT=NONE] -->
   <string name="dialog_sign_in_options_button">Sign-in Options</string>
+  <!-- Title for multiple credentials folded screen. [CHAR LIMIT=NONE] -->
+  <string name="sign_in_options_title">Sign-in Options</string>
   <!-- Title for multiple credentials flattened screen. [CHAR LIMIT=NONE] -->
   <string name="choose_sign_in_title">Choose a sign in</string>
 </resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
new file mode 100644
index 0000000..11188b4
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenScreen.kt
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.credentialmanager.ui.screens.multiple
+
+import android.graphics.drawable.Drawable
+import com.android.credentialmanager.ui.screens.UiState
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.navigation.NavHostController
+import androidx.navigation.compose.rememberNavController
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import com.android.credentialmanager.ui.components.SignInHeader
+import com.android.credentialmanager.CredentialSelectorUiState.Get.MultipleEntry
+import com.android.credentialmanager.R
+import com.android.credentialmanager.activity.StartBalIntentSenderForResultContract
+import com.android.credentialmanager.model.get.ActionEntryInfo
+import com.android.credentialmanager.model.get.CredentialEntryInfo
+import com.android.credentialmanager.ui.components.CredentialsScreenChip
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+import com.google.android.horologist.compose.layout.ScalingLazyColumn
+import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+
+
+/**
+ * Screen that shows multiple credentials to select from, grouped by accounts
+ *
+ * @param credentialSelectorUiState The app bar view model.
+ * @param screenIcon The view model corresponding to the home page.
+ * @param columnState ScalingLazyColumn configuration to be be applied
+ * @param modifier styling for composable
+ * @param viewModel ViewModel that updates ui state for this screen
+ * @param navController handles navigation events from this screen
+ */
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+fun MultiCredentialsFlattenScreen(
+    credentialSelectorUiState: MultipleEntry,
+    screenIcon: Drawable?,
+    columnState: ScalingLazyColumnState,
+    modifier: Modifier = Modifier,
+    viewModel: MultiCredentialsFlattenViewModel = hiltViewModel(),
+    navController: NavHostController = rememberNavController(),
+) {
+    val uiState by viewModel.uiState.collectAsStateWithLifecycle()
+
+    when (val state = uiState) {
+        UiState.CredentialScreen -> {
+            MultiCredentialsFlattenScreen(
+                state = credentialSelectorUiState,
+                columnState = columnState,
+                screenIcon = screenIcon,
+                onActionEntryClicked = viewModel::onActionEntryClicked,
+                onCredentialClicked = viewModel::onCredentialClicked,
+                modifier = modifier,
+            )
+        }
+
+        is UiState.CredentialSelected -> {
+            val launcher = rememberLauncherForActivityResult(
+                StartBalIntentSenderForResultContract()
+            ) {
+                viewModel.onInfoRetrieved(it.resultCode, null)
+            }
+
+            SideEffect {
+                state.intentSenderRequest?.let {
+                    launcher.launch(it)
+                }
+            }
+        }
+
+        UiState.Cancel -> {
+            navController.popBackStack()
+        }
+    }
+}
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+fun MultiCredentialsFlattenScreen(
+    state: MultipleEntry,
+    columnState: ScalingLazyColumnState,
+    screenIcon: Drawable?,
+    onActionEntryClicked: (entryInfo: ActionEntryInfo) -> Unit,
+    onCredentialClicked: (entryInfo: CredentialEntryInfo) -> Unit,
+    modifier: Modifier,
+) {
+    ScalingLazyColumn(
+        columnState = columnState,
+        modifier = modifier.fillMaxSize(),
+    ) {
+        item {
+            // make this credential specific if all credentials are same
+            SignInHeader(
+                icon = screenIcon,
+                title = stringResource(R.string.sign_in_options_title),
+            )
+        }
+
+        state.accounts.forEach { userNameEntries ->
+            item {
+                Text(
+                    text = userNameEntries.userName,
+                    modifier = Modifier
+                        .padding(top = 6.dp)
+                        .padding(horizontal = 10.dp),
+                    style = MaterialTheme.typography.title3
+                )
+            }
+
+            userNameEntries.sortedCredentialEntryList.forEach { credential: CredentialEntryInfo ->
+                item {
+                    CredentialsScreenChip(
+                        label = credential.userName,
+                        onClick = { onCredentialClicked(credential) },
+                        secondaryLabel = credential.userName,
+                        icon = credential.icon,
+                        modifier = modifier,
+                    )
+                }
+            }
+        }
+        item {
+            Text(
+                text = "Manage Sign-ins",
+                modifier = Modifier
+                    .padding(top = 6.dp)
+                    .padding(horizontal = 10.dp),
+                style = MaterialTheme.typography.title3
+            )
+        }
+
+        state.actionEntryList.forEach {
+            item {
+                    CredentialsScreenChip(
+                        label = it.title,
+                        onClick = { onActionEntryClicked(it) },
+                        secondaryLabel = null,
+                        icon = it.icon,
+                        modifier = modifier,
+                    )
+            }
+        }
+    }
+}
+
+
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenViewModel.kt
new file mode 100644
index 0000000..ee5f3f4
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/multiple/MultiCredentialsFlattenViewModel.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.credentialmanager.ui.screens.multiple
+
+import android.content.Intent
+import android.credentials.selection.ProviderPendingIntentResponse
+import android.credentials.selection.UserSelectionDialogResult
+import androidx.lifecycle.ViewModel
+import com.android.credentialmanager.client.CredentialManagerClient
+import com.android.credentialmanager.ktx.getIntentSenderRequest
+import com.android.credentialmanager.model.Request
+import com.android.credentialmanager.model.get.ActionEntryInfo
+import com.android.credentialmanager.model.get.CredentialEntryInfo
+import com.android.credentialmanager.ui.screens.UiState
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import javax.inject.Inject
+
+/** ViewModel for [MultiCredentialsFlattenScreen].*/
+@HiltViewModel
+class MultiCredentialsFlattenViewModel @Inject constructor(
+    private val credentialManagerClient: CredentialManagerClient,
+) : ViewModel() {
+
+    private lateinit var requestGet: Request.Get
+    private lateinit var entryInfo: CredentialEntryInfo
+
+    private val _uiState =
+        MutableStateFlow<UiState>(UiState.CredentialScreen)
+    val uiState: StateFlow<UiState> = _uiState
+
+    fun onCredentialClicked(entryInfo: CredentialEntryInfo) {
+        this.entryInfo = entryInfo
+        _uiState.value = UiState.CredentialSelected(
+            intentSenderRequest = entryInfo.getIntentSenderRequest()
+        )
+    }
+
+    fun onCancelClicked() {
+        _uiState.value = UiState.Cancel
+    }
+
+    fun onInfoRetrieved(
+        resultCode: Int? = null,
+        resultData: Intent? = null,
+    ) {
+        val userSelectionDialogResult = UserSelectionDialogResult(
+            requestGet.token,
+            entryInfo.providerId,
+            entryInfo.entryKey,
+            entryInfo.entrySubkey,
+            if (resultCode != null) ProviderPendingIntentResponse(resultCode, resultData) else null
+        )
+        credentialManagerClient.sendResult(userSelectionDialogResult)
+    }
+
+    fun onActionEntryClicked(actionEntryInfo: ActionEntryInfo) {
+        // TODO(b/322797032)to be filled out
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
index a8be944..29b9572 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreen.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
index 3f841b8..8debecb 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/single/password/SinglePasswordScreenViewModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.