Merge "Imporved the styles."
This commit is contained in:
@@ -2,11 +2,12 @@
|
||||
<resources>
|
||||
|
||||
<style name="Theme.CredentialSelector" parent="@android:style/ThemeOverlay.Material">
|
||||
<item name="android:statusBarColor">@color/purple_700</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="fontFamily">google-sans</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.common.ui
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SuggestionChip
|
||||
import androidx.compose.material3.SuggestionChipDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.android.credentialmanager.ui.theme.EntryShape
|
||||
import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun Entry(
|
||||
onClick: () -> Unit,
|
||||
label: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
onClick = onClick,
|
||||
shape = EntryShape.FullSmallRoundedCorner,
|
||||
label = label,
|
||||
icon = icon,
|
||||
border = null,
|
||||
colors = SuggestionChipDefaults.suggestionChipColors(
|
||||
containerColor = LocalAndroidColorScheme.current.colorSurface,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TransparentBackgroundEntry(
|
||||
onClick: () -> Unit,
|
||||
label: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: @Composable (() -> Unit)? = null,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
onClick = onClick,
|
||||
label = label,
|
||||
icon = icon,
|
||||
border = null,
|
||||
colors = SuggestionChipDefaults.suggestionChipColors(
|
||||
containerColor = Color.Transparent,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -17,7 +17,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SuggestionChip
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TopAppBar
|
||||
@@ -43,6 +42,7 @@ import com.android.credentialmanager.common.material.ModalBottomSheetValue
|
||||
import com.android.credentialmanager.common.material.rememberModalBottomSheetState
|
||||
import com.android.credentialmanager.common.ui.CancelButton
|
||||
import com.android.credentialmanager.common.ui.ConfirmButton
|
||||
import com.android.credentialmanager.common.ui.Entry
|
||||
import com.android.credentialmanager.ui.theme.EntryShape
|
||||
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
|
||||
|
||||
@@ -184,7 +184,7 @@ fun ProviderSelectionCard(
|
||||
color = Color.Transparent
|
||||
)
|
||||
Card(
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.align(alignment = Alignment.CenterHorizontally),
|
||||
@@ -257,7 +257,7 @@ fun MoreOptionsSelectionCard(
|
||||
color = Color.Transparent
|
||||
)
|
||||
Card(
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.align(alignment = Alignment.CenterHorizontally)
|
||||
@@ -356,20 +356,17 @@ fun MoreOptionsRowIntroCard(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ProviderRow(providerInfo: ProviderInfo, onProviderSelected: (String) -> Unit) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = {onProviderSelected(providerInfo.name)},
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
|
||||
Image(modifier = Modifier.size(32.dp).padding(start = 10.dp),
|
||||
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
|
||||
// painter = painterResource(R.drawable.ic_passkey),
|
||||
// TODO: add description.
|
||||
contentDescription = "")
|
||||
},
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
label = {
|
||||
Text(
|
||||
text = providerInfo.displayName,
|
||||
@@ -433,7 +430,7 @@ fun CreationSelectionCard(
|
||||
)
|
||||
}
|
||||
Card(
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.align(alignment = Alignment.CenterHorizontally),
|
||||
@@ -499,15 +496,13 @@ fun PrimaryCreateOptionRow(
|
||||
createOptionInfo: CreateOptionInfo,
|
||||
onOptionSelected: () -> Unit
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = onOptionSelected,
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
|
||||
Image(modifier = Modifier.size(32.dp).padding(start = 10.dp),
|
||||
bitmap = createOptionInfo.credentialTypeIcon.toBitmap().asImageBitmap(),
|
||||
contentDescription = null)
|
||||
},
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
label = {
|
||||
Column() {
|
||||
// TODO: Add the function to hide/view password when the type is create password
|
||||
@@ -542,15 +537,13 @@ fun MoreOptionsInfoRow(
|
||||
createOptionInfo: CreateOptionInfo,
|
||||
onOptionSelected: () -> Unit
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = onOptionSelected,
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(32.dp, 32.dp).padding(start = 16.dp),
|
||||
Image(modifier = Modifier.size(32.dp).padding(start = 16.dp),
|
||||
bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
|
||||
contentDescription = null)
|
||||
},
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
label = {
|
||||
Column() {
|
||||
Text(
|
||||
@@ -611,8 +604,7 @@ fun MoreOptionsDisabledProvidersRow(
|
||||
disabledProviders: List<ProviderInfo>,
|
||||
onDisabledPasswordManagerSelected: () -> Unit,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = onDisabledPasswordManagerSelected,
|
||||
icon = {
|
||||
Icon(
|
||||
@@ -621,7 +613,6 @@ fun MoreOptionsDisabledProvidersRow(
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
},
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
label = {
|
||||
Column() {
|
||||
Text(
|
||||
@@ -644,8 +635,7 @@ fun MoreOptionsDisabledProvidersRow(
|
||||
fun RemoteEntryRow(
|
||||
onRemoteEntrySelected: () -> Unit,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = onRemoteEntrySelected,
|
||||
icon = {
|
||||
Icon(
|
||||
@@ -655,7 +645,6 @@ fun RemoteEntryRow(
|
||||
modifier = Modifier.padding(start = 18.dp)
|
||||
)
|
||||
},
|
||||
shape = EntryShape.FullRoundedCorner,
|
||||
label = {
|
||||
Column() {
|
||||
Text(
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.Card
|
||||
@@ -33,7 +34,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SuggestionChip
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
@@ -46,6 +46,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.android.credentialmanager.R
|
||||
@@ -53,6 +54,8 @@ import com.android.credentialmanager.common.material.ModalBottomSheetLayout
|
||||
import com.android.credentialmanager.common.material.ModalBottomSheetValue
|
||||
import com.android.credentialmanager.common.material.rememberModalBottomSheetState
|
||||
import com.android.credentialmanager.common.ui.CancelButton
|
||||
import com.android.credentialmanager.common.ui.Entry
|
||||
import com.android.credentialmanager.common.ui.TransparentBackgroundEntry
|
||||
import com.android.credentialmanager.jetpack.developer.PublicKeyCredential
|
||||
|
||||
@Composable
|
||||
@@ -107,6 +110,9 @@ fun PrimarySelectionCard(
|
||||
Card() {
|
||||
Column() {
|
||||
Text(
|
||||
modifier = Modifier.padding(all = 24.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
text = stringResource(
|
||||
if (sortedUserNameToCredentialEntryList.size == 1) {
|
||||
if (sortedUserNameToCredentialEntryList.first().sortedCredentialEntryList
|
||||
@@ -117,12 +123,10 @@ fun PrimarySelectionCard(
|
||||
} else R.string.get_dialog_title_choose_sign_in_for,
|
||||
requestDisplayInfo.appDomainName
|
||||
),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(all = 24.dp).align(alignment = Alignment.CenterHorizontally)
|
||||
)
|
||||
|
||||
Card(
|
||||
shape = MaterialTheme.shapes.large,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.align(alignment = Alignment.CenterHorizontally)
|
||||
@@ -254,9 +258,14 @@ fun ActionChips(
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
// TODO: tweak padding.
|
||||
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
actionChips.forEach {
|
||||
ActionEntryRow(it, onEntrySelected)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
actionChips.forEach {
|
||||
ActionEntryRow(it, onEntrySelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,8 +280,18 @@ fun LockedCredentials(
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
authenticationEntryList.forEach {
|
||||
AuthenticationEntryRow(it, onEntrySelected)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
authenticationEntryList.forEach {
|
||||
AuthenticationEntryRow(it, onEntrySelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,8 +306,18 @@ fun PerUserNameCredentials(
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
)
|
||||
perUserNameCredentialEntryList.sortedCredentialEntryList.forEach {
|
||||
CredentialEntryRow(it, onEntrySelected)
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().wrapContentHeight(),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
perUserNameCredentialEntryList.sortedCredentialEntryList.forEach {
|
||||
CredentialEntryRow(it, onEntrySelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,16 +327,14 @@ fun CredentialEntryRow(
|
||||
credentialEntryInfo: CredentialEntryInfo,
|
||||
onEntrySelected: (EntryInfo) -> Unit,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = {onEntrySelected(credentialEntryInfo)},
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
|
||||
Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
|
||||
bitmap = credentialEntryInfo.icon.toBitmap().asImageBitmap(),
|
||||
// TODO: add description.
|
||||
contentDescription = "")
|
||||
},
|
||||
shape = MaterialTheme.shapes.large,
|
||||
label = {
|
||||
Column() {
|
||||
// TODO: fix the text values.
|
||||
@@ -338,16 +365,14 @@ fun AuthenticationEntryRow(
|
||||
authenticationEntryInfo: AuthenticationEntryInfo,
|
||||
onEntrySelected: (EntryInfo) -> Unit,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = {onEntrySelected(authenticationEntryInfo)},
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
|
||||
Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
|
||||
bitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
|
||||
// TODO: add description.
|
||||
contentDescription = "")
|
||||
},
|
||||
shape = MaterialTheme.shapes.large,
|
||||
label = {
|
||||
Column() {
|
||||
// TODO: fix the text values.
|
||||
@@ -372,16 +397,13 @@ fun ActionEntryRow(
|
||||
actionEntryInfo: ActionEntryInfo,
|
||||
onEntrySelected: (EntryInfo) -> Unit,
|
||||
) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = { onEntrySelected(actionEntryInfo) },
|
||||
TransparentBackgroundEntry(
|
||||
icon = {
|
||||
Image(modifier = Modifier.size(24.dp, 24.dp).padding(start = 10.dp),
|
||||
Image(modifier = Modifier.padding(start = 10.dp).size(32.dp),
|
||||
bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
|
||||
// TODO: add description.
|
||||
contentDescription = "")
|
||||
},
|
||||
shape = MaterialTheme.shapes.large,
|
||||
label = {
|
||||
Column() {
|
||||
Text(
|
||||
@@ -395,17 +417,16 @@ fun ActionEntryRow(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onClick = { onEntrySelected(actionEntryInfo) },
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SignInAnotherWayRow(onSelect: () -> Unit) {
|
||||
SuggestionChip(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
Entry(
|
||||
onClick = onSelect,
|
||||
shape = MaterialTheme.shapes.large,
|
||||
label = {
|
||||
Text(
|
||||
text = stringResource(R.string.get_dialog_use_saved_passkey_for),
|
||||
|
||||
@@ -64,8 +64,6 @@ class CredentialEntryInfo(
|
||||
val lastUsedTimeMillis: Long?,
|
||||
) : EntryInfo(providerId, entryKey, entrySubkey)
|
||||
|
||||
// TODO: handle sub credential type values like password obfuscation.
|
||||
|
||||
class AuthenticationEntryInfo(
|
||||
providerId: String,
|
||||
entryKey: String,
|
||||
|
||||
@@ -39,7 +39,32 @@ val LocalAndroidColorScheme =
|
||||
*/
|
||||
class AndroidColorScheme internal constructor(context: Context) {
|
||||
|
||||
val colorPrimary = getColor(context, R.attr.colorPrimary)
|
||||
val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
|
||||
val colorAccent = getColor(context, R.attr.colorAccent)
|
||||
val colorAccentPrimary = getColor(context, R.attr.colorAccentPrimary)
|
||||
val colorAccentSecondary = getColor(context, R.attr.colorAccentSecondary)
|
||||
val colorAccentTertiary = getColor(context, R.attr.colorAccentTertiary)
|
||||
val colorAccentPrimaryVariant = getColor(context, R.attr.colorAccentPrimaryVariant)
|
||||
val colorAccentSecondaryVariant = getColor(context, R.attr.colorAccentSecondaryVariant)
|
||||
val colorAccentTertiaryVariant = getColor(context, R.attr.colorAccentTertiaryVariant)
|
||||
val colorSurface = getColor(context, R.attr.colorSurface)
|
||||
val colorSurfaceHighlight = getColor(context, R.attr.colorSurfaceHighlight)
|
||||
val colorSurfaceVariant = getColor(context, R.attr.colorSurfaceVariant)
|
||||
val colorSurfaceHeader = getColor(context, R.attr.colorSurfaceHeader)
|
||||
val colorError = getColor(context, R.attr.colorError)
|
||||
val colorBackground = getColor(context, R.attr.colorBackground)
|
||||
val colorBackgroundFloating = getColor(context, R.attr.colorBackgroundFloating)
|
||||
val panelColorBackground = getColor(context, R.attr.panelColorBackground)
|
||||
val textColorPrimary = getColor(context, R.attr.textColorPrimary)
|
||||
val textColorSecondary = getColor(context, R.attr.textColorSecondary)
|
||||
val textColorTertiary = getColor(context, R.attr.textColorTertiary)
|
||||
val textColorPrimaryInverse = getColor(context, R.attr.textColorPrimaryInverse)
|
||||
val textColorSecondaryInverse = getColor(context, R.attr.textColorSecondaryInverse)
|
||||
val textColorTertiaryInverse = getColor(context, R.attr.textColorTertiaryInverse)
|
||||
val textColorOnAccent = getColor(context, R.attr.textColorOnAccent)
|
||||
val colorForeground = getColor(context, R.attr.colorForeground)
|
||||
val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)
|
||||
|
||||
private fun getColor(context: Context, attr: Int): Color {
|
||||
val ta = context.obtainStyledAttributes(intArrayOf(attr))
|
||||
|
||||
@@ -6,11 +6,15 @@ import androidx.compose.ui.unit.dp
|
||||
|
||||
val Shapes = Shapes(
|
||||
small = RoundedCornerShape(100.dp),
|
||||
medium = RoundedCornerShape(20.dp),
|
||||
medium = RoundedCornerShape(28.dp),
|
||||
large = RoundedCornerShape(0.dp)
|
||||
)
|
||||
|
||||
object EntryShape {
|
||||
val TopRoundedCorner = RoundedCornerShape(28.dp, 28.dp, 0.dp, 0.dp)
|
||||
val FullRoundedCorner = RoundedCornerShape(28.dp, 28.dp, 28.dp, 28.dp)
|
||||
val BottomRoundedCorner = RoundedCornerShape(0.dp, 0.dp, 28.dp, 28.dp)
|
||||
// Used for middle entries.
|
||||
val FullSmallRoundedCorner = RoundedCornerShape(4.dp, 4.dp, 4.dp, 4.dp)
|
||||
// Used for when there's a single entry.
|
||||
val FullMediumRoundedCorner = RoundedCornerShape(28.dp, 28.dp, 28.dp, 28.dp)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user