[Room Details] Implement room details screen (#256)

* Implement Room Details screen

* Add option to create permalink from room id and alias, add share room action
This commit is contained in:
Jorge Martin Espinosa 2023-03-29 07:16:27 +02:00 committed by GitHub
parent 4a121fbd0f
commit ecc73dd325
83 changed files with 1203 additions and 117 deletions

View file

@ -69,3 +69,6 @@ val ElementOrange = Color(0xFFD9B072)
val Vermilion = Color(0xFFFF5B55)
val LinkColor = Color(0xFF0086E6)
val TextColorCriticalLight = Color(0xFFD51928)
val TextColorCriticalDark = Color(0xfffd3e3c)

View file

@ -28,3 +28,12 @@ fun Boolean.toEnabledColor(): Color {
MaterialTheme.colorScheme.primary.copy(alpha = 0.40f)
}
}
@Composable
fun Boolean.toSecondaryEnabledColor(): Color {
return if (this) {
MaterialTheme.colorScheme.secondary
} else {
MaterialTheme.colorScheme.secondary.copy(alpha = 0.40f)
}
}

View file

@ -18,5 +18,7 @@ package io.element.android.libraries.designsystem.components.preferences
import androidx.compose.ui.unit.dp
internal val preferenceMinHeight = 80.dp
internal val preferencePaddingEnd = 16.dp
internal val preferenceMinHeightOnlyTitle = 48.dp
internal val preferenceMinHeight = 64.dp
internal val preferencePaddingHorizontal = 16.dp
internal val preferencePaddingVertical = 16.dp

View file

@ -35,29 +35,35 @@ import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun PreferenceCategory(
title: String,
modifier: Modifier = Modifier,
title: String? = null,
showDivider: Boolean = true,
content: @Composable ColumnScope.() -> Unit,
) {
Column(
modifier = modifier
.fillMaxWidth()
) {
Divider(
modifier = Modifier.padding(horizontal = 16.dp),
color = MaterialTheme.colorScheme.secondary,
thickness = 1.dp
)
Text(
modifier = Modifier.padding(top = 8.dp, start = 56.dp),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.primary,
text = title,
)
if (title != null) {
PreferenceCategoryTitle(title = title)
}
content()
if (showDivider) {
PreferenceDivider()
}
}
}
@Composable
fun PreferenceCategoryTitle(title: String, modifier: Modifier = Modifier) {
Text(
modifier = modifier.padding(top = 12.dp, start = 16.dp, end = 16.dp),
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.primary,
text = title,
)
}
@Preview
@Composable
internal fun PreferenceCategoryLightPreview() = ElementPreviewLight { ContentToPreview() }

View file

@ -0,0 +1,27 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* 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 io.element.android.libraries.designsystem.components.preferences
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.theme.components.Divider
@Composable
fun PreferenceDivider(modifier: Modifier = Modifier) {
Divider(modifier, thickness = 0.5.dp)
}

View file

@ -29,7 +29,6 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Announcement
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
@ -39,10 +38,9 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
@ -92,12 +90,7 @@ fun PreferenceTopAppBar(
TopAppBar(
modifier = modifier,
navigationIcon = {
IconButton(onClick = onBackPressed) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back"
)
}
BackButton(onClick = onBackPressed)
},
title = {
Row(verticalAlignment = Alignment.CenterVertically) {
@ -132,13 +125,16 @@ private fun ContentToPreview() {
) {
PreferenceText(
title = "Title",
subtitle = "Some other text",
icon = Icons.Default.BugReport,
)
PreferenceDivider()
PreferenceSwitch(
title = "Switch",
icon = Icons.Default.Announcement,
isChecked = true
isChecked = true,
)
PreferenceDivider()
PreferenceSlide(
title = "Slide",
summary = "Summary",

View file

@ -23,9 +23,10 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
@ -51,15 +52,15 @@ fun PreferenceSlide(
Box(
modifier = modifier
.fillMaxWidth()
.defaultMinSize(minHeight = preferenceMinHeight),
contentAlignment = Alignment.CenterStart
.defaultMinSize(minHeight = preferenceMinHeight)
.padding(top = preferencePaddingVertical),
) {
Row(modifier = Modifier.fillMaxWidth()) {
PreferenceIcon(icon = icon)
Column(
modifier = Modifier
.weight(1f)
.padding(end = preferencePaddingEnd),
.padding(end = preferencePaddingHorizontal),
) {
Text(
modifier = Modifier.fillMaxWidth(),
@ -97,6 +98,7 @@ internal fun PreferenceSlideDarkPreview() = ElementPreviewDark { ContentToPrevie
@Composable
private fun ContentToPreview() {
PreferenceSlide(
icon = Icons.Default.Person,
title = "Slide",
summary = "Summary",
value = 0.75F

View file

@ -53,22 +53,20 @@ fun PreferenceSwitch(
.clickable { onCheckedChange(!isChecked) },
contentAlignment = Alignment.CenterStart
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Row(modifier = Modifier.fillMaxWidth()) {
PreferenceIcon(
modifier = Modifier.padding(vertical = preferencePaddingVertical),
icon = icon,
enabled = enabled
)
Text(
modifier = Modifier.weight(1f),
modifier = Modifier.weight(1f).padding(vertical = preferencePaddingVertical),
style = MaterialTheme.typography.bodyLarge,
color = enabled.toEnabledColor(),
text = title
)
Checkbox(
modifier = Modifier.padding(end = preferencePaddingEnd),
modifier = Modifier.padding(end = preferencePaddingHorizontal).align(Alignment.CenterVertically),
checked = isChecked,
enabled = enabled,
onCheckedChange = onCheckedChange

View file

@ -18,18 +18,24 @@ package io.element.android.libraries.designsystem.components.preferences
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.components.preferences.components.PreferenceIcon
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
@ -37,31 +43,52 @@ import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun PreferenceText(
title: String,
// TODO subtitle
title: String?,
modifier: Modifier = Modifier,
subtitle: String? = null,
currentValue: String? = null,
icon: ImageVector? = null,
tintColor: Color? = null,
onClick: () -> Unit = {},
) {
val minHeight = if (subtitle == null) preferenceMinHeightOnlyTitle else preferenceMinHeight
Box(
modifier = modifier
.fillMaxWidth()
.defaultMinSize(minHeight = preferenceMinHeight)
.defaultMinSize(minHeight = minHeight)
.padding(end = preferencePaddingHorizontal)
.clickable { onClick() },
contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().padding(vertical = preferencePaddingVertical)
) {
PreferenceIcon(icon = icon)
Text(
modifier = Modifier
.weight(1f)
.padding(end = preferencePaddingEnd),
style = MaterialTheme.typography.bodyLarge,
text = title,
color = MaterialTheme.colorScheme.primary,
)
PreferenceIcon(icon = icon, tintColor = tintColor)
Column(modifier = Modifier
.weight(1f)
.align(Alignment.CenterVertically)
) {
if (title != null) {
Text(
style = MaterialTheme.typography.bodyLarge,
text = title,
color = tintColor ?: MaterialTheme.colorScheme.primary,
)
}
if (title != null && subtitle != null) {
Spacer(modifier = Modifier.height(8.dp))
}
if (subtitle != null) {
Text(
style = MaterialTheme.typography.bodySmall,
text = subtitle,
color = tintColor ?: MaterialTheme.colorScheme.tertiary,
)
}
}
if (currentValue != null) {
Text(currentValue, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.secondary)
Spacer(Modifier.width(16.dp))
}
}
}
}
@ -78,6 +105,7 @@ internal fun PreferenceTextDarkPreview() = ElementPreviewDark { ContentToPreview
private fun ContentToPreview() {
PreferenceText(
title = "Title",
subtitle = "Some content",
icon = Icons.Default.BugReport,
)
}

View file

@ -17,10 +17,12 @@
package io.element.android.libraries.designsystem.components.preferences.components
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -28,25 +30,30 @@ import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.toEnabledColor
import io.element.android.libraries.designsystem.toSecondaryEnabledColor
@Composable
fun PreferenceIcon(
icon: ImageVector?,
modifier: Modifier = Modifier,
enabled: Boolean = true
tintColor: Color? = null,
enabled: Boolean = true,
isVisible: Boolean = true,
) {
if (icon != null) {
Icon(
imageVector = icon,
contentDescription = "",
tint = enabled.toEnabledColor(),
tint = tintColor ?: enabled.toSecondaryEnabledColor(),
modifier = modifier
.padding(start = 8.dp)
.width(48.dp),
.width(48.dp)
.heightIn(max = 48.dp),
)
} else {
} else if (isVisible) {
Spacer(modifier = modifier.width(56.dp))
} else {
Spacer(modifier = modifier.width(16.dp))
}
}

View file

@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.Gray_400
import io.element.android.libraries.designsystem.Gray_450
import io.element.android.libraries.designsystem.SystemGrey5Dark
import io.element.android.libraries.designsystem.SystemGrey6Dark
import io.element.android.libraries.designsystem.TextColorCriticalDark
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
fun elementColorsDark() = ElementColors(
@ -37,6 +38,7 @@ fun elementColorsDark() = ElementColors(
messageHighlightedBackground = Azure,
quaternary = Gray_400,
quinary = Gray_450,
textActionCritical = TextColorCriticalDark,
isLight = false,
)
@ -69,7 +71,7 @@ val materialColorSchemeDark = darkColorScheme(
// TODO errorContainer = ColorDarkTokens.ErrorContainer,
// TODO onErrorContainer = ColorDarkTokens.OnErrorContainer,
// TODO outline = ColorDarkTokens.Outline,
// TODO outlineVariant = ColorDarkTokens.OutlineVariant,
outlineVariant = Gray_450,
// TODO scrim = ColorDarkTokens.Scrim,
)

View file

@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.Gray_25
import io.element.android.libraries.designsystem.Gray_50
import io.element.android.libraries.designsystem.SystemGrey5Light
import io.element.android.libraries.designsystem.SystemGrey6Light
import io.element.android.libraries.designsystem.TextColorCriticalLight
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
fun elementColorsLight() = ElementColors(
@ -37,6 +38,7 @@ fun elementColorsLight() = ElementColors(
messageHighlightedBackground = Azure,
quaternary = Gray_100,
quinary = Gray_50,
textActionCritical = TextColorCriticalLight,
isLight = true,
)
@ -69,7 +71,7 @@ val materialColorSchemeLight = lightColorScheme(
// TODO errorContainer = ColorLightTokens.ErrorContainer,
// TODO onErrorContainer = ColorLightTokens.OnErrorContainer,
// TODO outline = ColorLightTokens.Outline,
// TODO outlineVariant = ColorLightTokens.OutlineVariant,
outlineVariant = Gray_50,
// TODO scrim = ColorLightTokens.Scrim,
)

View file

@ -29,7 +29,8 @@ class ElementColors(
messageHighlightedBackground: Color,
quaternary: Color,
quinary: Color,
isLight: Boolean,
textActionCritical: Color,
isLight: Boolean
) {
var messageFromMeBackground by mutableStateOf(messageFromMeBackground)
private set
@ -44,6 +45,9 @@ class ElementColors(
var quinary by mutableStateOf(quinary)
private set
var textActionCritical by mutableStateOf(textActionCritical)
private set
var isLight by mutableStateOf(isLight)
private set
@ -53,6 +57,7 @@ class ElementColors(
messageHighlightedBackground: Color = this.messageHighlightedBackground,
quaternary: Color = this.quaternary,
quinary: Color = this.quinary,
textActionCritical: Color = this.textActionCritical,
isLight: Boolean = this.isLight,
) = ElementColors(
messageFromMeBackground = messageFromMeBackground,
@ -60,6 +65,7 @@ class ElementColors(
messageHighlightedBackground = messageHighlightedBackground,
quaternary = quaternary,
quinary = quinary,
textActionCritical = textActionCritical,
isLight = isLight,
)
@ -69,6 +75,7 @@ class ElementColors(
messageHighlightedBackground = other.messageHighlightedBackground
quaternary = other.quaternary
quinary = other.quinary
textActionCritical = other.textActionCritical
isLight = other.isLight
}
}

View file

@ -38,7 +38,7 @@ fun TopAppBar(
navigationIcon: @Composable () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors(),
colors: TopAppBarColors = TopAppBarDefaults.topAppBarColors(),
scrollBehavior: TopAppBarScrollBehavior? = null
) {
androidx.compose.material3.TopAppBar(