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:
@@ -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() {
|
||||
|
||||
15
packages/CredentialManager/res/drawable/ic_other_devices.xml
Normal file
15
packages/CredentialManager/res/drawable/ic_other_devices.xml
Normal 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>
|
||||
@@ -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. -->
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user