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

Commit b2ed1ebf authored by Helen Qin's avatar Helen Qin Committed by Android (Google) Code Review
Browse files

Merge "Add remote entry for get flow."

parents 588f9096 594e4c3b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -62,4 +62,8 @@
  <string name="locked_credential_entry_label_subtext">Tap to unlock</string>
  <!-- Column heading for displaying action chips for managing sign-ins from each credential provider. [CHAR LIMIT=80] -->
  <string name="get_dialog_heading_manage_sign_ins">Manage sign-ins</string>
  <!-- Column heading for displaying option to use sign-ins saved on a different device. [CHAR LIMIT=80] -->
  <string name="get_dialog_heading_from_another_device">From another device</string>
  <!-- Headline text for an option to use sign-ins saved on a different device. [CHAR LIMIT=120] -->
  <string name="get_dialog_option_headline_use_a_different_device">Use a different device</string>
</resources>
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ class CredentialManagerRepo(
          )
        )
        .setRemoteEntry(
          newRemoteEntry("key1", "subkey-1")
          newRemoteEntry("key2", "subkey-1")
        )
        .setIsDefaultProvider(true)
        .build(),
@@ -252,6 +252,8 @@ class CredentialManagerRepo(
              "Open Google Password Manager", "beckett-family@gmail.com"
            ),
          )
        ).setRemoteEntry(
          newRemoteEntry("key4", "subkey-1")
        ).build(),
      GetCredentialProviderData.Builder("com.dashlane")
        .setCredentialEntries(
+18 −4
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
import com.android.credentialmanager.getflow.ProviderInfo
import com.android.credentialmanager.getflow.RemoteEntryInfo
import com.android.credentialmanager.jetpack.provider.ActionUi
import com.android.credentialmanager.jetpack.provider.CredentialEntryUi
import com.android.credentialmanager.jetpack.provider.SaveEntryUi
@@ -63,6 +64,7 @@ class GetFlowUtils {
            providerDisplayName,
            providerIcon,
            it.authenticationEntry),
          remoteEntry = getRemoteEntry(it.providerFlattenedComponentName, it.remoteEntry),
          actionEntryList = getActionEntryList(
            it.providerFlattenedComponentName, it.actionChips, context),
        )
@@ -116,6 +118,18 @@ class GetFlowUtils {
      )
    }

    private fun getRemoteEntry(providerId: String, remoteEntry: Entry?): RemoteEntryInfo? {
      // TODO: should also call fromSlice after getting the official jetpack code.
      if (remoteEntry == null) {
        return null
      }
      return RemoteEntryInfo(
        providerId = providerId,
        entryKey = remoteEntry.key,
        entrySubkey = remoteEntry.subkey,
      )
    }

    private fun getActionEntryList(
      providerId: String,
      actionEntries: List<Entry>,
+55 −4
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -220,16 +221,25 @@ fun AllSignInOptionCard(
            )
          }
          // Locked password manager
          item {
          if (!authenticationEntryList.isEmpty()) {
            item {
              LockedCredentials(
                authenticationEntryList = authenticationEntryList,
                onEntrySelected = onEntrySelected,
              )
            }
          }
          // TODO: Remote action
          // Manage sign-ins
          // From another device
          val remoteEntry = providerDisplayInfo.remoteEntry
          if (remoteEntry != null) {
            item {
              RemoteEntryCard(
                remoteEntry = remoteEntry,
                onEntrySelected = onEntrySelected,
              )
            }
          }
          // Manage sign-ins (action chips)
          item {
            ActionChips(providerInfoList = providerInfoList, onEntrySelected = onEntrySelected)
          }
@@ -270,6 +280,47 @@ fun ActionChips(
  }
}

@Composable
fun RemoteEntryCard(
  remoteEntry: RemoteEntryInfo,
  onEntrySelected: (EntryInfo) -> Unit,
) {
  Text(
    text = stringResource(R.string.get_dialog_heading_from_another_device),
    style = MaterialTheme.typography.labelLarge,
    modifier = Modifier.padding(vertical = 8.dp)
  )
  Card(
    modifier = Modifier.fillMaxWidth().wrapContentHeight(),
    shape = MaterialTheme.shapes.medium,
  ) {
    Column(
      modifier = Modifier.fillMaxWidth().wrapContentHeight(),
      verticalArrangement = Arrangement.spacedBy(2.dp),
    ) {
      Entry(
        onClick = {onEntrySelected(remoteEntry)},
        icon = {
          Icon(
            painter = painterResource(R.drawable.ic_other_devices),
            contentDescription = null,
            tint = Color.Unspecified,
            modifier = Modifier.padding(start = 18.dp)
          )
        },
        label = {
          Text(
            text = stringResource(R.string.get_dialog_option_headline_use_a_different_device),
            style = MaterialTheme.typography.titleLarge,
            modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
              .align(alignment = Alignment.CenterHorizontally)
          )
        }
      )
    }
  }
}

@Composable
fun LockedCredentials(
  authenticationEntryList: List<AuthenticationEntryInfo>,
+9 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.credentialmanager.CredentialManagerRepo
import com.android.credentialmanager.common.DialogResult
import com.android.credentialmanager.common.ResultState
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
import com.android.internal.util.Preconditions

data class GetCredentialUiState(
  val providerInfoList: List<ProviderInfo>,
@@ -86,10 +87,14 @@ private fun toProviderDisplayInfo(

  val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
  val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
  val remoteEntryList = mutableListOf<RemoteEntryInfo>()
  providerInfoList.forEach { providerInfo ->
    if (providerInfo.authenticationEntry != null) {
      authenticationEntryList.add(providerInfo.authenticationEntry)
    }
    if (providerInfo.remoteEntry != null) {
      remoteEntryList.add(providerInfo.remoteEntry)
    }

    providerInfo.credentialEntryList.forEach {
      userNameToCredentialEntryMap.compute(
@@ -105,6 +110,9 @@ private fun toProviderDisplayInfo(
      }
    }
  }
  // There can only be at most one remote entry
  // TODO: fail elegantly
  Preconditions.checkState(remoteEntryList.size <= 1)

  // Compose sortedUserNameToCredentialEntryList
  val comparator = CredentialEntryInfoComparator()
@@ -122,6 +130,7 @@ private fun toProviderDisplayInfo(
  return ProviderDisplayInfo(
    sortedUserNameToCredentialEntryList = sortedUserNameToCredentialEntryList,
    authenticationEntryList = authenticationEntryList,
    remoteEntry = remoteEntryList.getOrNull(0),
  )
}

Loading