Merge changes Ie96bf43d,Ib0572d4b

* changes:
  Update the intro screen after select on a more options row
  Add the Another device row in the more options screen
This commit is contained in:
Qinmei Du
2022-11-11 23:31:12 +00:00
committed by Android (Google) Code Review
8 changed files with 145 additions and 17 deletions

View File

@@ -131,6 +131,13 @@ public class CreateCredentialProviderData extends ProviderData implements Parcel
return this;
}
/** Sets the remote entry of the provider. */
@NonNull
public Builder setRemoteEntry(@Nullable Entry remoteEntry) {
mRemoteEntry = remoteEntry;
return this;
}
/** Builds a {@link CreateCredentialProviderData}. */
@NonNull
public CreateCredentialProviderData build() {

View File

@@ -0,0 +1,15 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="VectorPath"
android:name="vector"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:name="path"
android:pathData="M 7.6 4.72 L 7.6 7.6 L 4.72 7.6 L 4.72 4.72 L 7.6 4.72 Z M 9.04 3.28 L 3.28 3.28 L 3.28 9.04 L 9.04 9.04 L 9.04 3.28 Z M 7.6 12.4 L 7.6 15.28 L 4.72 15.28 L 4.72 12.4 L 7.6 12.4 Z M 9.04 10.96 L 3.28 10.96 L 3.28 16.72 L 9.04 16.72 L 9.04 10.96 Z M 15.28 4.72 L 15.28 7.6 L 12.4 7.6 L 12.4 4.72 L 15.28 4.72 Z M 16.72 3.28 L 10.96 3.28 L 10.96 9.04 L 16.72 9.04 L 16.72 3.28 Z M 10.96 10.96 L 12.4 10.96 L 12.4 12.4 L 10.96 12.4 L 10.96 10.96 Z M 12.4 12.4 L 13.84 12.4 L 13.84 13.84 L 12.4 13.84 L 12.4 12.4 Z M 13.84 10.96 L 15.28 10.96 L 15.28 12.4 L 13.84 12.4 L 13.84 10.96 Z M 10.96 13.84 L 12.4 13.84 L 12.4 15.28 L 10.96 15.28 L 10.96 13.84 Z M 12.4 15.28 L 13.84 15.28 L 13.84 16.72 L 12.4 16.72 L 12.4 15.28 Z M 13.84 13.84 L 15.28 13.84 L 15.28 15.28 L 13.84 15.28 L 13.84 13.84 Z M 15.28 12.4 L 16.72 12.4 L 16.72 13.84 L 15.28 13.84 L 15.28 12.4 Z M 15.28 15.28 L 16.72 15.28 L 16.72 16.72 L 15.28 16.72 L 15.28 15.28 Z M 19.6 5.2 L 17.68 5.2 L 17.68 2.32 L 14.8 2.32 L 14.8 0.4 L 19.6 0.4 L 19.6 5.2 Z M 19.6 19.6 L 19.6 14.8 L 17.68 14.8 L 17.68 17.68 L 14.8 17.68 L 14.8 19.6 L 19.6 19.6 Z M 0.4 19.6 L 5.2 19.6 L 5.2 17.68 L 2.32 17.68 L 2.32 14.8 L 0.4 14.8 L 0.4 19.6 Z M 0.4 0.4 L 0.4 5.2 L 2.32 5.2 L 2.32 2.32 L 5.2 2.32 L 5.2 0.4 L 0.4 0.4 Z"
android:fillColor="#000000"
android:strokeWidth="1"/>
</vector>

View File

@@ -28,7 +28,10 @@
<string name="passkey">passkey</string>
<string name="password">password</string>
<string name="sign_ins">sign-ins</string>
<string name="another_device">Another device</string>
<string name="other_password_manager">Other password manager</string>
<!-- TODO: Check the wording here. -->
<string name="confirm_default_or_use_once_description">This password manager will store your passwords and passkeys to help you easily sign in.</string>
<!-- Spoken content description of an element which will close the sheet when clicked. -->
<string name="close_sheet">"Close sheet"</string>
<!-- Spoken content description of the back arrow button. -->

View File

@@ -181,6 +181,9 @@ class CredentialManagerRepo(
20, 7, 27, 11000),
)
)
.setRemoteEntry(
newRemoteEntry("key1", "subkey-1")
)
.setIsDefaultProvider(true)
.build(),
CreateCredentialProviderData
@@ -308,6 +311,19 @@ class CredentialManagerRepo(
)
}
private fun newRemoteEntry(
key: String,
subkey: String,
): Entry {
return Entry(
key,
subkey,
Slice.Builder(
Entry.CREDENTIAL_MANAGER_ENTRY_URI, SliceSpec(Entry.VERSION, 1)
).build()
)
}
private fun testCreateRequestInfo(): RequestInfo {
val data = Bundle()
return RequestInfo.newCreateRequestInfo(

View File

@@ -23,6 +23,7 @@ import android.credentials.ui.GetCredentialProviderData
import android.credentials.ui.CreateCredentialProviderData
import android.credentials.ui.DisabledProviderData
import com.android.credentialmanager.createflow.CreateOptionInfo
import com.android.credentialmanager.createflow.RemoteInfo
import com.android.credentialmanager.getflow.ActionEntryInfo
import com.android.credentialmanager.getflow.AuthenticationEntryInfo
import com.android.credentialmanager.getflow.CredentialEntryInfo
@@ -120,6 +121,7 @@ class CreateFlowUtils {
displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(),
createOptions = toCreationOptionInfoList(it.saveEntries, context),
isDefault = it.isDefaultProvider,
remoteEntry = toRemoteInfo(it.remoteEntry),
)
}
}
@@ -164,5 +166,17 @@ class CreateFlowUtils {
)
}
}
private fun toRemoteInfo(
remoteEntry: Entry?,
): RemoteInfo? {
// TODO: should also call fromSlice after getting the official jetpack code.
return if (remoteEntry != null) {
RemoteInfo(
entryKey = remoteEntry.key,
entrySubkey = remoteEntry.subkey,
)
} else null
}
}
}

View File

@@ -30,6 +30,7 @@ class EnabledProviderInfo(
displayName: String,
var createOptions: List<CreateOptionInfo>,
val isDefault: Boolean,
var remoteEntry: RemoteInfo?,
) : ProviderInfo(icon, name, displayName)
class DisabledProviderInfo(
@@ -55,6 +56,11 @@ class CreateOptionInfo(
val lastUsedTimeMillis: Long?,
) : EntryInfo(entryKey, entrySubkey)
class RemoteInfo(
entryKey: String,
entrySubkey: String,
) : EntryInfo(entryKey, entrySubkey)
data class RequestDisplayInfo(
val userName: String,
val displayName: String,

View File

@@ -21,6 +21,7 @@ import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.outlined.NewReleases
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -80,7 +81,8 @@ fun CreatePasskeyScreen(
disabledProviderList = uiState.disabledProviders,
onBackButtonSelected = viewModel::onBackButtonSelected,
onOptionSelected = viewModel::onMoreOptionsRowSelected,
onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected
onDisabledPasswordManagerSelected = viewModel::onDisabledPasswordManagerSelected,
onRemoteEntrySelected = viewModel::onRemoteEntrySelected
)
CreateScreenState.MORE_OPTIONS_ROW_INTRO -> MoreOptionsRowIntroCard(
providerInfo = uiState.activeEntry?.activeProvider!!,
@@ -216,10 +218,11 @@ fun ProviderSelectionCard(
fun MoreOptionsSelectionCard(
requestDisplayInfo: RequestDisplayInfo,
enabledProviderList: List<EnabledProviderInfo>,
disabledProviderList: List<DisabledProviderInfo>,
disabledProviderList: List<DisabledProviderInfo>?,
onBackButtonSelected: () -> Unit,
onOptionSelected: (ActiveEntry) -> Unit,
onDisabledPasswordManagerSelected: () -> Unit,
onRemoteEntrySelected: () -> Unit,
) {
Card() {
Column() {
@@ -267,11 +270,26 @@ fun MoreOptionsSelectionCard(
}
}
}
item {
MoreOptionsDisabledProvidersRow(
disabledProviders = disabledProviderList,
onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
)
if (disabledProviderList != null) {
item {
MoreOptionsDisabledProvidersRow(
disabledProviders = disabledProviderList,
onDisabledPasswordManagerSelected = onDisabledPasswordManagerSelected,
)
}
}
var hasRemoteInfo = false
enabledProviderList.forEach {
if (it.remoteEntry != null) {
hasRemoteInfo = true
}
}
if (hasRemoteInfo) {
item {
RemoteEntryRow(
onRemoteEntrySelected = onRemoteEntrySelected,
)
}
}
}
}
@@ -292,9 +310,21 @@ fun MoreOptionsRowIntroCard(
) {
Card() {
Column() {
Icon(
Icons.Outlined.NewReleases,
contentDescription = null,
modifier = Modifier.align(alignment = Alignment.CenterHorizontally).padding(all = 24.dp)
)
Text(
text = stringResource(R.string.use_provider_for_all_title, providerInfo.displayName),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier.padding(horizontal = 24.dp)
.align(alignment = Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
)
Text(
text = stringResource(R.string.confirm_default_or_use_once_description),
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
)
Row(
@@ -498,7 +528,7 @@ fun MoreOptionsInfoRow(
modifier = Modifier.fillMaxWidth(),
onClick = onOptionSelected,
icon = {
Image(modifier = Modifier.size(32.dp, 32.dp).padding(start = 10.dp),
Image(modifier = Modifier.size(32.dp, 32.dp).padding(start = 16.dp),
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
contentDescription = null)
},
@@ -508,12 +538,14 @@ fun MoreOptionsInfoRow(
Text(
text = providerInfo.displayName,
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(top = 16.dp)
modifier = Modifier.padding(top = 16.dp, start = 16.dp)
)
if (createOptionInfo.userProviderDisplayName != null) {
Text(
text = createOptionInfo.userProviderDisplayName,
style = MaterialTheme.typography.bodyMedium)
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(start = 16.dp)
)
}
if (createOptionInfo.passwordCount != null && createOptionInfo.passkeyCount != null) {
Text(
@@ -524,7 +556,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passkeyCount
),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 16.dp)
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.passwordCount != null) {
Text(
@@ -534,7 +566,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passwordCount
),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 16.dp)
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.passkeyCount != null) {
Text(
@@ -544,7 +576,7 @@ fun MoreOptionsInfoRow(
createOptionInfo.passkeyCount
),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 16.dp)
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
} else if (createOptionInfo.totalCredentialCount != null) {
// TODO: Handle the case when there is total count
@@ -567,7 +599,8 @@ fun MoreOptionsDisabledProvidersRow(
icon = {
Icon(
Icons.Filled.Add,
contentDescription = null
contentDescription = null,
modifier = Modifier.padding(start = 16.dp)
)
},
shape = MaterialTheme.shapes.large,
@@ -576,12 +609,42 @@ fun MoreOptionsDisabledProvidersRow(
Text(
text = stringResource(R.string.other_password_manager),
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(top = 16.dp)
modifier = Modifier.padding(top = 16.dp, start = 16.dp)
)
Text(
text = disabledProviders.joinToString(separator = ", "){ it.displayName },
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.padding(bottom = 16.dp)
modifier = Modifier.padding(bottom = 16.dp, start = 16.dp)
)
}
}
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RemoteEntryRow(
onRemoteEntrySelected: () -> Unit,
) {
SuggestionChip(
modifier = Modifier.fillMaxWidth(),
onClick = onRemoteEntrySelected,
icon = {
Icon(
painter = painterResource(R.drawable.ic_other_devices),
contentDescription = null,
tint = Color.Unspecified,
modifier = Modifier.padding(start = 18.dp)
)
},
shape = MaterialTheme.shapes.large,
label = {
Column() {
Text(
text = stringResource(R.string.another_device),
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(start = 16.dp, top = 18.dp, bottom = 18.dp)
.align(alignment = Alignment.CenterHorizontally)
)
}
}

View File

@@ -29,7 +29,7 @@ import com.android.credentialmanager.common.ResultState
data class CreatePasskeyUiState(
val enabledProviders: List<EnabledProviderInfo>,
val disabledProviders: List<DisabledProviderInfo>,
val disabledProviders: List<DisabledProviderInfo>? = null,
val currentScreenState: CreateScreenState,
val requestDisplayInfo: RequestDisplayInfo,
val activeEntry: ActiveEntry? = null,
@@ -103,6 +103,10 @@ class CreatePasskeyViewModel(
// TODO: Complete this function
}
fun onRemoteEntrySelected() {
// TODO: Complete this function
}
fun onCancel() {
CredentialManagerRepo.getInstance().onCancel()
dialogResult.value = DialogResult(ResultState.CANCELED)