Improve themes, styling and animations
parent
89d93bc80d
commit
ff64a8bc13
@ -0,0 +1,174 @@
|
|||||||
|
package org.thoughtcrime.securesms.ui.components
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.foundation.BorderStroke
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.interaction.PressInteraction
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.ButtonDefaults
|
||||||
|
import androidx.compose.material.ContentAlpha
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.OutlinedButton
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.material.TextButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Shape
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.TextUnit
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import org.thoughtcrime.securesms.ui.GetString
|
||||||
|
import org.thoughtcrime.securesms.ui.LaunchedEffectAsync
|
||||||
|
import org.thoughtcrime.securesms.ui.LocalButtonColor
|
||||||
|
import org.thoughtcrime.securesms.ui.colorDestructive
|
||||||
|
import org.thoughtcrime.securesms.ui.contentDescription
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
|
val LocalButtonSize = staticCompositionLocalOf { mediumButton }
|
||||||
|
val LocalButtonShape = staticCompositionLocalOf<Shape> { RoundedCornerShape(percent = 50) }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun Modifier.applyButtonSize() = then(LocalButtonSize.current)
|
||||||
|
|
||||||
|
val mediumButton = Modifier.height(41.dp)
|
||||||
|
val smallButton = Modifier.wrapContentHeight()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OutlineButton(@StringRes textId: Int, modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||||
|
OutlineButton(stringResource(textId), modifier, onClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||||
|
OutlineButton(modifier.contentDescription(text), onClick = onClick) { Text(text) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun OutlineButton(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
|
onClick: () -> Unit,
|
||||||
|
content: @Composable () -> Unit = {}
|
||||||
|
) {
|
||||||
|
OutlinedButton(
|
||||||
|
modifier = modifier.applyButtonSize(),
|
||||||
|
interactionSource = interactionSource,
|
||||||
|
onClick = onClick,
|
||||||
|
border = BorderStroke(1.dp, LocalButtonColor.current),
|
||||||
|
shape = LocalButtonShape.current,
|
||||||
|
colors = ButtonDefaults.outlinedButtonColors(
|
||||||
|
contentColor = LocalButtonColor.current,
|
||||||
|
backgroundColor = Color.Unspecified
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TemporaryStateButton(
|
||||||
|
content: @Composable (MutableInteractionSource, Boolean) -> Unit,
|
||||||
|
) {
|
||||||
|
val interactions = remember { MutableInteractionSource() }
|
||||||
|
|
||||||
|
var clicked by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
content(interactions, clicked)
|
||||||
|
|
||||||
|
LaunchedEffectAsync {
|
||||||
|
interactions.releases.collectLatest {
|
||||||
|
clicked = true
|
||||||
|
delay(2.seconds)
|
||||||
|
clicked = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun FilledButton(
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
OutlinedButton(
|
||||||
|
modifier = modifier.size(108.dp, 34.dp),
|
||||||
|
onClick = onClick,
|
||||||
|
shape = RoundedCornerShape(50),
|
||||||
|
colors = ButtonDefaults.outlinedButtonColors(
|
||||||
|
contentColor = MaterialTheme.colors.background,
|
||||||
|
backgroundColor = LocalButtonColor.current
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(text = text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BorderlessButtonSecondary(
|
||||||
|
text: String,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
BorderlessButton(
|
||||||
|
text,
|
||||||
|
contentColor = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium),
|
||||||
|
onClick = onClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BorderlessButton(
|
||||||
|
text: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
contentDescription: GetString = GetString(text),
|
||||||
|
fontSize: TextUnit = TextUnit.Unspecified,
|
||||||
|
lineHeight: TextUnit = TextUnit.Unspecified,
|
||||||
|
contentColor: Color = MaterialTheme.colors.onBackground,
|
||||||
|
backgroundColor: Color = Color.Transparent,
|
||||||
|
onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
TextButton(
|
||||||
|
onClick = onClick,
|
||||||
|
modifier = modifier.contentDescription(contentDescription),
|
||||||
|
shape = RoundedCornerShape(percent = 50),
|
||||||
|
colors = ButtonDefaults.outlinedButtonColors(
|
||||||
|
contentColor = contentColor,
|
||||||
|
backgroundColor = backgroundColor
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = text,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
fontSize = fontSize,
|
||||||
|
lineHeight = lineHeight,
|
||||||
|
modifier = Modifier.padding(horizontal = 2.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val MutableInteractionSource.releases
|
||||||
|
get() = interactions.filter { it is PressInteraction.Release }
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SmallButtons(content: @Composable () -> Unit) {
|
||||||
|
CompositionLocalProvider(LocalButtonSize provides smallButton) { content() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun DestructiveButtons(content: @Composable () -> Unit) {
|
||||||
|
CompositionLocalProvider(LocalButtonColor provides colorDestructive) { content() }
|
||||||
|
}
|
Loading…
Reference in New Issue