M3 tweaks (#796)

* Refine chips in collection list

* Refine PermissionSwitchRow

* Collections list

* Fix WelcomePage and IntroActivity background color in dark mode

* Fix RadioWithSwitch in dark mode

* Drawer handler: branding in dark mode
This commit is contained in:
Ricki Hirner 2024-05-16 16:45:40 +02:00 committed by GitHub
parent 6f02669832
commit 5cc29fc58a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 180 additions and 119 deletions

View file

@ -46,6 +46,7 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import at.bitfire.davdroid.BuildConfig
@ -80,7 +81,7 @@ abstract class AccountsDrawerHandler {
.fillMaxWidth()
.verticalScroll(rememberScrollState())
) {
Header()
BrandingHeader()
val closeDrawerHandler = object : CloseDrawerHandler() {
override fun closeDrawer() {
@ -176,47 +177,6 @@ abstract class AccountsDrawerHandler {
// building blocks
@Composable
fun Header() {
Column(
Modifier
.background(Color.DarkGray)
.fillMaxWidth()
.padding(16.dp)
) {
Spacer(Modifier.height(16.dp))
Box(
Modifier.background(
color = MaterialTheme.colorScheme.primary,
shape = RoundedCornerShape(16.dp)
)
) {
Icon(
painterResource(R.drawable.ic_launcher_foreground),
stringResource(R.string.app_name),
tint = Color.White,
modifier = Modifier
.scale(1.2f)
.size(64.dp)
)
}
Spacer(Modifier.height(8.dp))
Text(
stringResource(R.string.app_name),
color = Color.White,
style = MaterialTheme.typography.bodyLarge
)
Text(
stringResource(R.string.navigation_drawer_subtitle),
color = Color.White.copy(alpha = 0.7f),
style = MaterialTheme.typography.bodyMedium
)
}
Spacer(Modifier.height(8.dp))
}
@Composable
fun MenuHeading(text: String) {
HorizontalDivider(Modifier.padding(vertical = 8.dp))
@ -262,4 +222,62 @@ abstract class AccountsDrawerHandler {
)
}
}
@Composable
fun BrandingHeader() {
Column(
Modifier
.background(Color.DarkGray)
.fillMaxWidth()
.padding(16.dp)
) {
Spacer(Modifier.height(16.dp))
Box(
Modifier.background(
color = M3ColorScheme.md_theme_light_primary,
shape = RoundedCornerShape(16.dp)
)
) {
Icon(
painterResource(R.drawable.ic_launcher_foreground),
stringResource(R.string.app_name),
tint = Color.White,
modifier = Modifier
.scale(1.2f)
.size(64.dp)
)
}
Spacer(Modifier.height(8.dp))
Text(
stringResource(R.string.app_name),
color = Color.White,
style = MaterialTheme.typography.bodyLarge
)
Text(
stringResource(R.string.navigation_drawer_subtitle),
color = Color.White.copy(alpha = 0.7f),
style = MaterialTheme.typography.bodyMedium
)
}
Spacer(Modifier.height(8.dp))
}
@Composable
@Preview
fun BrandingHeader_Preview_Light() {
AppTheme(useDarkTheme = false) {
BrandingHeader()
}
}
@Composable
@Preview
fun BrandingHeader_Preview_Dark() {
AppTheme(useDarkTheme = true) {
BrandingHeader()
}
}

View file

@ -56,6 +56,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode

View file

@ -364,9 +364,10 @@ fun AccountScreen(
idxCalDav -> {
val permissions = mutableListOf(Manifest.permission.WRITE_CALENDAR)
TaskUtils.currentProvider(context)?.let { tasksProvider ->
permissions += tasksProvider.permissions
}
if (!LocalInspectionMode.current) // TaskUtils.currentProvider prevents preview
TaskUtils.currentProvider(context)?.let { tasksProvider ->
permissions += tasksProvider.permissions
}
AccountScreen_ServiceTab(
requiredPermissions = permissions,
progress = calDavProgress,

View file

@ -17,7 +17,9 @@ import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.EventNote
import androidx.compose.material.icons.filled.Contacts
@ -29,7 +31,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.SuggestionChip
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@ -198,6 +199,7 @@ fun CollectionsList_Item_Standard_Preview() {
displayName = "Sample Calendar",
description = "This Sample Calendar even has some lengthy description.",
color = 0xffff0000.toInt(),
sync = true,
forceReadOnly = true,
supportsVEVENT = true,
supportsVTODO = true,
@ -243,9 +245,21 @@ fun CollectionList_Item_Webcal_Preview() {
@Composable
fun CollectionList_Item_Chip(icon: ImageVector, text: String) {
SuggestionChip(
icon = { Icon(icon, contentDescription = text) },
label = { Text(text) },
onClick = {}
)
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.background(MaterialTheme.colorScheme.surfaceVariant, shape = RoundedCornerShape(8.dp))
.padding(horizontal = 8.dp, vertical = 4.dp)
) {
Icon(
icon,
contentDescription = text,
modifier = Modifier.size(20.dp)
)
Text(
text,
style = MaterialTheme.typography.labelMedium,
modifier = Modifier.padding(start = 4.dp)
)
}
}

View file

@ -7,6 +7,10 @@ package at.bitfire.davdroid.ui.composable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
@ -16,6 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberMultiplePermissionsState
@ -50,7 +55,15 @@ fun PermissionSwitchRow(
}
Switch(
checked = allPermissionsGranted,
enabled = !allPermissionsGranted,
thumbContent = if (allPermissionsGranted) {
{
Icon(
Icons.Default.Check,
contentDescription = null,
modifier = Modifier.padding(4.dp)
)
}
} else null,
onCheckedChange = { checked ->
if (checked) {
onLaunchRequest()

View file

@ -8,13 +8,11 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.ContentAlpha
import androidx.compose.material.LocalContentColor
import androidx.compose.material.MaterialTheme
import androidx.compose.material.ProvideTextStyle
import androidx.compose.material.RadioButton
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.Role
@ -31,8 +29,7 @@ import androidx.compose.ui.tooling.preview.Preview
* @param isSelected Whether the item is currently selected. Refers to the radio button.
* @param isToggled Whether the switch is toggled.
* @param modifier Any modifiers to apply to the row.
* @param enabled Whether the radio button should be enabled. The enabled state of the switch is
* reverse from this. So if it's `true`, the switch will be disabled.
* @param enabled Whether the radio button should be enabled.
* @param onSelected Gets called whenever the user requests this row to be enabled. Either by
* selecting the radio button or tapping the text.
* @param onToggled Gets called whenever the switch gets updated. Contains the checked status.
@ -58,20 +55,11 @@ fun RadioWithSwitch(
) {
Text(
text = title,
color = LocalContentColor.current.copy(
alpha = if (enabled) 1f else ContentAlpha.disabled
),
style = MaterialTheme.typography.body1,
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.fillMaxWidth()
)
summary?.let { sum ->
ProvideTextStyle(
value = MaterialTheme.typography.body2.copy(
color = LocalContentColor.current.copy(
alpha = if (enabled) 1f else ContentAlpha.disabled
)
)
) {
ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
sum()
}
}
@ -79,8 +67,7 @@ fun RadioWithSwitch(
Switch(
checked = isToggled,
onCheckedChange = onToggled,
enabled = !enabled
onCheckedChange = onToggled
)
}
}

View file

@ -14,7 +14,9 @@ import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.ComposeView
@ -89,8 +91,10 @@ class IntroActivity : AppIntro2() {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
AppTheme {
Box(Modifier.padding(bottom = dimensionResource(com.github.appintro.R.dimen.appintro2_bottombar_height))) {
page.ComposePage()
Surface(Modifier.fillMaxSize()) {
Box(Modifier.padding(bottom = dimensionResource(com.github.appintro.R.dimen.appintro2_bottombar_height))) {
page.ComposePage()
}
}
}
}

View file

@ -30,6 +30,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import at.bitfire.davdroid.R
import at.bitfire.davdroid.ui.AppTheme
import at.bitfire.davdroid.ui.M3ColorScheme
class WelcomePage: IntroPage {
@ -44,16 +46,12 @@ class WelcomePage: IntroPage {
}
@Preview(
device = "id:3.7in WVGA (Nexus One)",
showSystemUi = true
)
@Composable
private fun ContentPortrait() {
Column(
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.primary),
.background(color = M3ColorScheme.md_theme_light_primary),
) {
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
@ -97,55 +95,80 @@ class WelcomePage: IntroPage {
}
}
@Composable
@Preview(
device = "id:3.7in WVGA (Nexus One)",
showSystemUi = true
)
fun Preview_ContentPortrait_Light() {
AppTheme(useDarkTheme = false) {
ContentPortrait()
}
}
@Composable
@Preview(
device = "id:3.7in WVGA (Nexus One)",
showSystemUi = true
)
fun Preview_ContentPortrait_Dark() {
AppTheme(useDarkTheme = true) {
ContentPortrait()
}
}
@Preview(
showSystemUi = true,
device = "id:medium_tablet"
)
@Composable
private fun ContentLandscape() {
Row(
modifier = Modifier
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.primary)
.padding(
bottom = dimensionResource(
com.github.appintro.R.dimen.appintro2_bottombar_height
)
),
verticalAlignment = Alignment.CenterVertically
) {
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = null,
AppTheme {
Row(
modifier = Modifier
.fillMaxHeight()
.weight(1f)
)
Column(
modifier = Modifier
.padding(horizontal = 32.dp)
.weight(2f)
.fillMaxSize()
.background(color = MaterialTheme.colorScheme.primary)
.padding(
bottom = dimensionResource(
com.github.appintro.R.dimen.appintro2_bottombar_height
)
),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = stringResource(R.string.intro_slogan1),
color = Color.White,
style = MaterialTheme.typography.bodyMedium.copy(fontSize = 34.sp),
lineHeight = 38.sp,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
Image(
painter = painterResource(R.drawable.ic_launcher_foreground),
contentDescription = null,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
)
Text(
text = stringResource(R.string.intro_slogan2),
color = Color.White,
style = MaterialTheme.typography.labelLarge.copy(fontSize = 48.sp),
lineHeight = 52.sp,
textAlign = TextAlign.Center,
Column(
modifier = Modifier
.padding(top = 16.dp)
.fillMaxWidth()
)
.padding(horizontal = 32.dp)
.weight(2f)
) {
Text(
text = stringResource(R.string.intro_slogan1),
color = Color.White,
style = MaterialTheme.typography.bodyMedium.copy(fontSize = 34.sp),
lineHeight = 38.sp,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
Text(
text = stringResource(R.string.intro_slogan2),
color = Color.White,
style = MaterialTheme.typography.labelLarge.copy(fontSize = 48.sp),
lineHeight = 52.sp,
textAlign = TextAlign.Center,
modifier = Modifier
.padding(top = 16.dp)
.fillMaxWidth()
)
}
}
}
}