[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:
parent
4a121fbd0f
commit
ecc73dd325
83 changed files with 1203 additions and 117 deletions
|
|
@ -69,3 +69,6 @@ val ElementOrange = Color(0xFFD9B072)
|
|||
val Vermilion = Color(0xFFFF5B55)
|
||||
|
||||
val LinkColor = Color(0xFF0086E6)
|
||||
|
||||
val TextColorCriticalLight = Color(0xFFD51928)
|
||||
val TextColorCriticalDark = Color(0xfffd3e3c)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue