session-android/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt

294 lines
9 KiB
Kotlin
Raw Normal View History

2023-06-29 09:41:11 +02:00
package org.thoughtcrime.securesms.ui
import androidx.annotation.DrawableRes
2023-09-26 07:27:28 +02:00
import androidx.compose.foundation.BorderStroke
2023-09-22 10:56:18 +02:00
import androidx.compose.foundation.Canvas
2023-07-03 05:30:11 +02:00
import androidx.compose.foundation.ExperimentalFoundationApi
2023-06-29 09:41:11 +02:00
import androidx.compose.foundation.layout.Box
2023-07-04 06:39:40 +02:00
import androidx.compose.foundation.layout.BoxScope
2023-07-04 05:56:26 +02:00
import androidx.compose.foundation.layout.RowScope
2023-07-03 11:00:15 +02:00
import androidx.compose.foundation.layout.Spacer
2023-06-29 09:41:11 +02:00
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
2023-09-22 10:56:18 +02:00
import androidx.compose.foundation.layout.size
2023-06-29 09:41:11 +02:00
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
2023-07-03 05:30:11 +02:00
import androidx.compose.foundation.pager.PagerState
2023-06-29 09:41:11 +02:00
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ButtonColors
2023-09-26 07:27:28 +02:00
import androidx.compose.material.ButtonDefaults
2023-06-29 11:44:47 +02:00
import androidx.compose.material.Card
2023-07-09 16:42:42 +02:00
import androidx.compose.material.Colors
2023-06-29 09:41:11 +02:00
import androidx.compose.material.Icon
2023-07-03 11:00:15 +02:00
import androidx.compose.material.IconButton
2023-06-29 11:44:47 +02:00
import androidx.compose.material.MaterialTheme
2023-09-26 07:27:28 +02:00
import androidx.compose.material.OutlinedButton
2023-06-29 09:41:11 +02:00
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
2023-07-03 11:00:15 +02:00
import androidx.compose.runtime.rememberCoroutineScope
2023-06-29 09:41:11 +02:00
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
2023-09-22 10:56:18 +02:00
import androidx.compose.ui.geometry.Size
2023-07-03 05:30:11 +02:00
import androidx.compose.ui.graphics.Color
2023-06-29 09:41:11 +02:00
import androidx.compose.ui.graphics.RectangleShape
2023-09-22 10:56:18 +02:00
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.Stroke
2023-06-29 09:41:11 +02:00
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
2023-10-16 16:26:55 +02:00
import androidx.compose.ui.unit.TextUnit
2023-06-29 09:41:11 +02:00
import androidx.compose.ui.unit.dp
2023-07-06 07:50:45 +02:00
import androidx.compose.ui.viewinterop.AndroidView
2023-07-03 05:30:11 +02:00
import com.google.accompanist.pager.HorizontalPagerIndicator
2023-07-03 11:00:15 +02:00
import kotlinx.coroutines.launch
import network.loki.messenger.R
2023-07-06 07:50:45 +02:00
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.components.ProfilePictureView
2023-09-22 10:56:18 +02:00
import kotlin.math.roundToInt
2023-07-09 16:42:42 +02:00
2023-09-26 07:27:28 +02:00
@Composable
fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) {
OutlinedButton(
modifier = modifier.size(108.dp, 34.dp),
onClick = onClick,
border = BorderStroke(1.dp, LocalExtraColors.current.prominentButtonColor),
shape = RoundedCornerShape(50), // = 50% percent
colors = ButtonDefaults.outlinedButtonColors(
contentColor = LocalExtraColors.current.prominentButtonColor,
backgroundColor = MaterialTheme.colors.background
)
2023-10-16 16:26:55 +02:00
) {
2023-09-26 07:27:28 +02:00
Text(text = text)
}
}
2023-10-16 16:26:55 +02:00
@Composable
fun FilledButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) {
OutlinedButton(
modifier = modifier.size(108.dp, 34.dp),
onClick = onClick,
shape = RoundedCornerShape(50), // = 50% percent
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.background,
backgroundColor = LocalExtraColors.current.prominentButtonColor
)
) {
Text(text = text)
}
}
@Composable
fun BorderlessButton(
text: String,
modifier: Modifier = Modifier,
fontSize: TextUnit = TextUnit.Unspecified,
lineHeight: TextUnit = TextUnit.Unspecified,
onClick: () -> Unit) {
TextButton(
onClick = onClick,
modifier = modifier,
shape = RoundedCornerShape(50), // = 50% percent
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.onBackground,
backgroundColor = MaterialTheme.colors.background
)
) {
Text(
text = text,
fontSize = fontSize,
lineHeight = lineHeight
)
}
}
2023-06-29 09:41:11 +02:00
@Composable
fun ItemButton(
text: String,
@DrawableRes icon: Int,
colors: ButtonColors = transparentButtonColors(),
2023-07-10 08:39:38 +02:00
contentDescription: String = text,
2023-06-30 02:18:48 +02:00
onClick: () -> Unit
2023-06-29 09:41:11 +02:00
) {
TextButton(
modifier = Modifier
.fillMaxWidth()
.height(60.dp),
colors = colors,
2023-06-30 02:18:48 +02:00
onClick = onClick,
2023-06-29 09:41:11 +02:00
shape = RectangleShape,
) {
Box(modifier = Modifier
.width(80.dp)
.fillMaxHeight()) {
Icon(
painter = painterResource(id = icon),
2023-07-10 08:39:38 +02:00
contentDescription = contentDescription,
2023-06-29 09:41:11 +02:00
modifier = Modifier.align(Alignment.Center)
)
}
Text(text, modifier = Modifier.fillMaxWidth())
}
}
@Composable
fun Cell(content: @Composable () -> Unit) {
2023-07-03 09:49:33 +02:00
CellWithPaddingAndMargin(padding = 0.dp) { content() }
2023-07-03 05:30:11 +02:00
}
@Composable
fun CellNoMargin(content: @Composable () -> Unit) {
2023-07-03 09:49:33 +02:00
CellWithPaddingAndMargin(padding = 0.dp, margin = 0.dp) { content() }
2023-06-29 09:41:11 +02:00
}
@Composable
2023-07-03 05:30:11 +02:00
fun CellWithPaddingAndMargin(
padding: Dp = 24.dp,
margin: Dp = 32.dp,
content: @Composable () -> Unit
) {
2023-07-10 05:31:46 +02:00
Card(
backgroundColor = MaterialTheme.colors.cellColor,
shape = RoundedCornerShape(16.dp),
elevation = 0.dp,
modifier = Modifier
.wrapContentHeight()
.fillMaxWidth()
.padding(horizontal = margin),
) {
Box(Modifier.padding(padding)) { content() }
2023-07-09 16:42:42 +02:00
}
2023-06-29 11:44:47 +02:00
}
2023-07-03 05:30:11 +02:00
2023-07-10 05:31:46 +02:00
private val Colors.cellColor: Color
@Composable
get() = LocalExtraColors.current.settingsBackground
2023-07-03 05:30:11 +02:00
@OptIn(ExperimentalFoundationApi::class)
@Composable
2023-07-04 06:39:40 +02:00
fun BoxScope.HorizontalPagerIndicator(pagerState: PagerState) {
2023-07-04 14:40:48 +02:00
if (pagerState.pageCount >= 2) Card(
shape = RoundedCornerShape(50.dp),
2023-07-03 05:30:11 +02:00
backgroundColor = Color.Black.copy(alpha = 0.4f),
2023-07-03 11:00:15 +02:00
modifier = Modifier
2023-07-04 06:39:40 +02:00
.align(Alignment.BottomCenter)
2023-07-04 14:40:48 +02:00
.padding(8.dp)
) {
2023-07-03 05:30:11 +02:00
Box(modifier = Modifier.padding(8.dp)) {
2023-07-03 12:42:23 +02:00
HorizontalPagerIndicator(
pagerState = pagerState,
2023-07-04 06:39:40 +02:00
pageCount = pagerState.pageCount,
2023-07-03 12:42:23 +02:00
activeColor = Color.White,
2023-07-09 16:42:42 +02:00
inactiveColor = classicDarkColors[5])
2023-07-03 05:30:11 +02:00
}
}
}
2023-07-03 11:00:15 +02:00
@OptIn(ExperimentalFoundationApi::class)
@Composable
2023-07-04 05:56:26 +02:00
fun RowScope.CarouselPrevButton(pagerState: PagerState) {
CarouselButton(pagerState, pagerState.canScrollBackward, R.drawable.ic_prev, -1)
2023-07-03 11:00:15 +02:00
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
2023-07-04 05:56:26 +02:00
fun RowScope.CarouselNextButton(pagerState: PagerState) {
CarouselButton(pagerState, pagerState.canScrollForward, R.drawable.ic_next, 1)
2023-07-03 11:00:15 +02:00
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
2023-07-04 05:56:26 +02:00
fun RowScope.CarouselButton(
2023-07-03 11:00:15 +02:00
pagerState: PagerState,
enabled: Boolean,
@DrawableRes id: Int,
2023-07-04 05:56:26 +02:00
delta: Int
2023-07-03 11:00:15 +02:00
) {
if (pagerState.pageCount <= 1) Spacer(modifier = Modifier.width(32.dp))
else {
val animationScope = rememberCoroutineScope()
IconButton(
modifier = Modifier
.width(40.dp)
2023-07-04 05:56:26 +02:00
.align(Alignment.CenterVertically),
2023-07-03 11:00:15 +02:00
enabled = enabled,
onClick = { animationScope.launch { pagerState.animateScrollToPage(pagerState.currentPage + delta) } }) {
Icon(
painter = painterResource(id = id),
contentDescription = "",
)
}
}
}
2023-07-03 13:55:59 +02:00
@Composable
fun Divider() {
androidx.compose.material.Divider(
modifier = Modifier.padding(horizontal = 16.dp),
)
}
2023-07-06 07:50:45 +02:00
@Composable
fun RowScope.Avatar(recipient: Recipient) {
Box(
modifier = Modifier
.width(60.dp)
.align(Alignment.CenterVertically)
) {
AndroidView(
factory = {
ProfilePictureView(it).apply { update(recipient) }
},
modifier = Modifier
.width(46.dp)
.height(46.dp)
)
}
}
2023-09-22 10:56:18 +02:00
@Composable
fun ProgressArc(progress: Float, modifier: Modifier = Modifier) {
val text = (progress * 100).roundToInt()
Box(modifier = modifier) {
Arc(percentage = progress, modifier = Modifier.align(Alignment.Center))
Text("${text}%", color = Color.White, modifier = Modifier.align(Alignment.Center), style = MaterialTheme.typography.h2)
}
}
@Composable
fun Arc(
modifier: Modifier = Modifier,
percentage: Float = 0.25f,
fillColor: Color = session_accent,
backgroundColor: Color = classicDarkColors[3],
strokeWidth: Dp = 18.dp,
sweepAngle: Float = 310f,
startAngle: Float = (360f - sweepAngle) / 2 + 90f
) {
Canvas(
modifier = modifier
.padding(strokeWidth)
.size(186.dp)
) {
// Background Line
drawArc(
color = backgroundColor,
startAngle,
sweepAngle,
false,
style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
size = Size(size.width, size.height)
)
drawArc(
color = fillColor,
startAngle,
percentage * sweepAngle,
false,
style = Stroke(strokeWidth.toPx(), cap = StrokeCap.Round),
size = Size(size.width, size.height)
)
}
}