@@ -18,16 +18,15 @@ package io.element.android.x
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.bumble.appyx.core.integration.NodeHost
|
||||
import com.bumble.appyx.core.integrationpoint.NodeComponentActivity
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.designsystem.ElementXTheme
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.x.di.AppBindings
|
||||
import io.element.android.x.node.RootFlowNode
|
||||
@@ -41,10 +40,9 @@ class MainActivity : NodeComponentActivity() {
|
||||
appBindings.matrixClientsHolder().restore(savedInstanceState)
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
setContent {
|
||||
ElementXTheme {
|
||||
Surface(
|
||||
ElementTheme {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
NodeHost(integrationPoint = appyxIntegrationPoint) {
|
||||
RootFlowNode(
|
||||
|
||||
@@ -20,13 +20,13 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
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.Text
|
||||
|
||||
@Composable
|
||||
internal fun ShowkaseButton(
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.squareup.anvil.annotations.ContributesTo
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.matrix.auth.MatrixAuthenticationService
|
||||
import io.element.android.x.root.RootPresenter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@ContributesTo(AppScope::class)
|
||||
interface AppBindings {
|
||||
|
||||
@@ -19,7 +19,6 @@ package io.element.android.x.node
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -37,6 +36,7 @@ import io.element.android.features.roomlist.RoomListNode
|
||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||
import io.element.android.libraries.architecture.bindings
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.libraries.matrix.MatrixClient
|
||||
import io.element.android.libraries.matrix.core.RoomId
|
||||
|
||||
@@ -19,7 +19,6 @@ package io.element.android.x.node
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -36,6 +35,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push
|
||||
import io.element.android.features.rageshake.bugreport.BugReportNode
|
||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.di.DaggerComponentOwner
|
||||
import io.element.android.libraries.matrix.auth.MatrixAuthenticationService
|
||||
import io.element.android.libraries.matrix.core.SessionId
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.features.login.changeserver
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
@@ -33,13 +31,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -57,6 +49,12 @@ import io.element.android.features.login.error.changeServerError
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.VectorIcon
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
|
||||
@@ -66,126 +64,129 @@ fun ChangeServerView(
|
||||
modifier: Modifier = Modifier,
|
||||
onChangeServerSuccess: () -> Unit = {},
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
val eventSink = state.eventSink
|
||||
val scrollState = rememberScrollState()
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
) {
|
||||
val eventSink = state.eventSink
|
||||
val scrollState = rememberScrollState()
|
||||
Box(
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
Column(
|
||||
val isError = state.changeServerAction is Async.Failure
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
.padding(top = 99.dp)
|
||||
.size(width = 81.dp, height = 73.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(32.dp)
|
||||
)
|
||||
.padding(horizontal = 16.dp)
|
||||
) {
|
||||
val isError = state.changeServerAction is Async.Failure
|
||||
Box(
|
||||
VectorIcon(
|
||||
modifier = Modifier
|
||||
.padding(top = 99.dp)
|
||||
.size(width = 81.dp, height = 73.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(32.dp)
|
||||
)
|
||||
) {
|
||||
VectorIcon(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Center)
|
||||
.size(width = 48.dp, height = 48.dp),
|
||||
// TODO Update with design input
|
||||
resourceId = R.drawable.ic_baseline_dataset_24,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = "Your server",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = 56.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 38.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
.align(Alignment.Center)
|
||||
.size(width = 48.dp, height = 48.dp),
|
||||
// TODO Update with design input
|
||||
resourceId = R.drawable.ic_baseline_dataset_24,
|
||||
)
|
||||
Text(
|
||||
text = "A server is a home for all your data.\n" +
|
||||
"You choose your server and it’s easy to make one.", // TODO "Learn more.",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 16.sp,
|
||||
color = MaterialTheme.colorScheme.secondary
|
||||
}
|
||||
Text(
|
||||
text = "Your server",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.defaultMinSize(minHeight = 56.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 38.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Text(
|
||||
text = "A server is a home for all your data.\n" +
|
||||
"You choose your server and it’s easy to make one.", // TODO "Learn more.",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(top = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontSize = 16.sp,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
var homeserverFieldState by textFieldState(stateValue = state.homeserver)
|
||||
OutlinedTextField(
|
||||
value = homeserverFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.changeServerServer)
|
||||
.padding(top = 200.dp),
|
||||
onValueChange = {
|
||||
homeserverFieldState = it
|
||||
eventSink(ChangeServerEvents.SetServer(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Server")
|
||||
},
|
||||
isError = isError,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { eventSink(ChangeServerEvents.Submit) }
|
||||
)
|
||||
var homeserverFieldState by textFieldState(stateValue = state.homeserver)
|
||||
OutlinedTextField(
|
||||
value = homeserverFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.changeServerServer)
|
||||
.padding(top = 200.dp),
|
||||
onValueChange = {
|
||||
homeserverFieldState = it
|
||||
eventSink(ChangeServerEvents.SetServer(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Server")
|
||||
},
|
||||
isError = isError,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
)
|
||||
if (state.changeServerAction is Async.Failure) {
|
||||
Text(
|
||||
text = changeServerError(
|
||||
state.homeserver,
|
||||
state.changeServerAction.error
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { eventSink(ChangeServerEvents.Submit) }
|
||||
)
|
||||
)
|
||||
if (state.changeServerAction is Async.Failure) {
|
||||
Text(
|
||||
text = changeServerError(
|
||||
state.homeserver,
|
||||
state.changeServerAction.error
|
||||
),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
Button(
|
||||
onClick = { eventSink(ChangeServerEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.changeServerContinue)
|
||||
.padding(top = 44.dp)
|
||||
) {
|
||||
Text(text = "Continue")
|
||||
}
|
||||
if (state.changeServerAction is Async.Success) {
|
||||
onChangeServerSuccess()
|
||||
}
|
||||
}
|
||||
if (state.changeServerAction is Async.Loading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
Button(
|
||||
onClick = { eventSink(ChangeServerEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.changeServerContinue)
|
||||
.padding(top = 44.dp)
|
||||
) {
|
||||
Text(text = "Continue")
|
||||
}
|
||||
if (state.changeServerAction is Async.Success) {
|
||||
onChangeServerSuccess()
|
||||
}
|
||||
}
|
||||
if (state.changeServerAction is Async.Loading) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ChangeServerContentPreview() {
|
||||
@Composable
|
||||
fun ChangeServerViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ChangeServerViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ChangeServerView(
|
||||
state = ChangeServerState(homeserver = "matrix.org"),
|
||||
)
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.features.login.root
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -32,15 +30,7 @@ import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.VisibilityOff
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -60,12 +50,19 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.login.error.loginError
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
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.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.core.SessionId
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun LoginRootScreen(
|
||||
state: LoginRootState,
|
||||
@@ -74,161 +71,164 @@ fun LoginRootScreen(
|
||||
onLoginWithSuccess: (SessionId) -> Unit = {},
|
||||
) {
|
||||
val eventSink = state.eventSink
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
) {
|
||||
Box(
|
||||
val scrollState = rememberScrollState()
|
||||
var loginFieldState by textFieldState(stateValue = state.formState.login)
|
||||
var passwordFieldState by textFieldState(stateValue = state.formState.password)
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
var loginFieldState by textFieldState(stateValue = state.formState.login)
|
||||
var passwordFieldState by textFieldState(stateValue = state.formState.password)
|
||||
|
||||
Column(
|
||||
val isError = state.loggedInState is LoggedInState.ErrorLoggingIn
|
||||
// Title
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.ftue_auth_welcome_back_title),
|
||||
modifier = Modifier
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 48.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
// Form
|
||||
Column(
|
||||
// modifier = Modifier.weight(1f),
|
||||
) {
|
||||
val isError = state.loggedInState is LoggedInState.ErrorLoggingIn
|
||||
// Title
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.ftue_auth_welcome_back_title),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 48.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
)
|
||||
// Form
|
||||
Column(
|
||||
// modifier = Modifier.weight(1f),
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = state.homeserver,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onValueChange = { /* no op */ },
|
||||
enabled = false,
|
||||
label = {
|
||||
Text(text = "Server")
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Uri,
|
||||
),
|
||||
)
|
||||
Button(
|
||||
onClick = onChangeServer,
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.testTag(TestTags.loginChangeServer)
|
||||
.padding(top = 8.dp, end = 8.dp),
|
||||
content = {
|
||||
Text(text = "Change")
|
||||
}
|
||||
)
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = loginFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginEmailUsername)
|
||||
.padding(top = 60.dp),
|
||||
value = state.homeserver,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onValueChange = { /* no op */ },
|
||||
enabled = false,
|
||||
label = {
|
||||
Text(text = stringResource(id = StringR.string.login_signin_username_hint))
|
||||
},
|
||||
onValueChange = {
|
||||
loginFieldState = it
|
||||
eventSink(LoginRootEvents.SetLogin(it))
|
||||
Text(text = "Server")
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Email,
|
||||
imeAction = ImeAction.Next
|
||||
keyboardType = KeyboardType.Uri,
|
||||
),
|
||||
)
|
||||
var passwordVisible by remember { mutableStateOf(false) }
|
||||
if (state.loggedInState is LoggedInState.LoggingIn) {
|
||||
// Ensure password is hidden when user submits the form
|
||||
passwordVisible = false
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = passwordFieldState,
|
||||
Button(
|
||||
onClick = onChangeServer,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginPassword)
|
||||
.padding(top = 24.dp),
|
||||
onValueChange = {
|
||||
passwordFieldState = it
|
||||
eventSink(LoginRootEvents.SetPassword(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Password")
|
||||
},
|
||||
isError = isError,
|
||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
val image =
|
||||
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
|
||||
val description =
|
||||
if (passwordVisible) "Hide password" else "Show password"
|
||||
.align(Alignment.CenterEnd)
|
||||
.testTag(TestTags.loginChangeServer)
|
||||
.padding(top = 8.dp, end = 8.dp),
|
||||
content = {
|
||||
Text(text = "Change")
|
||||
}
|
||||
)
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = loginFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginEmailUsername)
|
||||
.padding(top = 60.dp),
|
||||
label = {
|
||||
Text(text = stringResource(id = StringR.string.login_signin_username_hint))
|
||||
},
|
||||
onValueChange = {
|
||||
loginFieldState = it
|
||||
eventSink(LoginRootEvents.SetLogin(it))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Email,
|
||||
imeAction = ImeAction.Next
|
||||
),
|
||||
)
|
||||
var passwordVisible by remember { mutableStateOf(false) }
|
||||
if (state.loggedInState is LoggedInState.LoggingIn) {
|
||||
// Ensure password is hidden when user submits the form
|
||||
passwordVisible = false
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = passwordFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginPassword)
|
||||
.padding(top = 24.dp),
|
||||
onValueChange = {
|
||||
passwordFieldState = it
|
||||
eventSink(LoginRootEvents.SetPassword(it))
|
||||
},
|
||||
label = {
|
||||
Text(text = "Password")
|
||||
},
|
||||
isError = isError,
|
||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||
trailingIcon = {
|
||||
val image =
|
||||
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
|
||||
val description =
|
||||
if (passwordVisible) "Hide password" else "Show password"
|
||||
|
||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||
Icon(imageVector = image, description)
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { eventSink(LoginRootEvents.Submit) }
|
||||
),
|
||||
)
|
||||
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
|
||||
Text(
|
||||
text = loginError(state.formState, state.loggedInState.failure),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
// Submit
|
||||
Button(
|
||||
onClick = { eventSink(LoginRootEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginContinue)
|
||||
.padding(vertical = 32.dp)
|
||||
) {
|
||||
Text(text = "Continue")
|
||||
}
|
||||
when (val loggedInState = state.loggedInState) {
|
||||
is LoggedInState.LoggedIn -> onLoginWithSuccess(loggedInState.sessionId)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
if (state.loggedInState is LoggedInState.LoggingIn) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||
Icon(imageVector = image, description)
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Password,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { eventSink(LoginRootEvents.Submit) }
|
||||
),
|
||||
)
|
||||
if (state.loggedInState is LoggedInState.ErrorLoggingIn) {
|
||||
Text(
|
||||
text = loginError(state.formState, state.loggedInState.failure),
|
||||
color = MaterialTheme.colorScheme.error,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
// Submit
|
||||
Button(
|
||||
onClick = { eventSink(LoginRootEvents.Submit) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.testTag(TestTags.loginContinue)
|
||||
.padding(vertical = 32.dp)
|
||||
) {
|
||||
Text(text = "Continue")
|
||||
}
|
||||
when (val loggedInState = state.loggedInState) {
|
||||
is LoggedInState.LoggedIn -> onLoginWithSuccess(loggedInState.sessionId)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
if (state.loggedInState is LoggedInState.LoggingIn) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun LoginContentPreview() {
|
||||
@Composable
|
||||
fun LoginRootScreenLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LoginRootScreenDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
LoginRootScreen(
|
||||
state = LoginRootState(
|
||||
homeserver = "matrix.org",
|
||||
|
||||
@@ -29,6 +29,8 @@ import io.element.android.libraries.designsystem.components.ProgressDialog
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceCategory
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -88,8 +90,15 @@ fun LogoutPreferenceContent(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun LogoutContentPreview() {
|
||||
@Composable
|
||||
fun LogoutPreferenceViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LogoutPreferenceViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
LogoutPreferenceView(LogoutPreferenceState())
|
||||
}
|
||||
|
||||
@@ -39,13 +39,8 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@@ -64,6 +59,11 @@ import io.element.android.features.messages.timeline.TimelineView
|
||||
import io.element.android.features.messages.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
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
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
||||
@@ -29,11 +29,10 @@ import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ListItem
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.ModalBottomSheetLayout
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@@ -44,6 +43,7 @@ import androidx.compose.ui.unit.dp
|
||||
import io.element.android.features.messages.actionlist.model.TimelineItemAction
|
||||
import io.element.android.features.messages.timeline.model.TimelineItem
|
||||
import io.element.android.libraries.designsystem.components.VectorIcon
|
||||
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheetLayout
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -85,7 +85,7 @@ fun ActionListView(
|
||||
.imePadding()
|
||||
)
|
||||
}
|
||||
) {}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -115,13 +115,13 @@ private fun SheetContent(
|
||||
text = {
|
||||
Text(
|
||||
text = action.title,
|
||||
color = if (action.destructive) MaterialTheme.colors.error else Color.Unspecified,
|
||||
color = if (action.destructive) MaterialTheme.colorScheme.error else Color.Unspecified,
|
||||
)
|
||||
},
|
||||
icon = {
|
||||
VectorIcon(
|
||||
resourceId = action.icon,
|
||||
tint = if (action.destructive) MaterialTheme.colors.error else LocalContentColor.current,
|
||||
tint = if (action.destructive) MaterialTheme.colorScheme.error else LocalContentColor.current,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -18,6 +18,7 @@ package io.element.android.features.messages.actionlist.model
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import io.element.android.libraries.designsystem.VectorIcons
|
||||
|
||||
@Immutable
|
||||
sealed class TimelineItemAction(
|
||||
@@ -25,9 +26,9 @@ sealed class TimelineItemAction(
|
||||
@DrawableRes val icon: Int,
|
||||
val destructive: Boolean = false
|
||||
) {
|
||||
object Forward : TimelineItemAction("Forward", io.element.android.libraries.designsystem.VectorIcons.ArrowForward)
|
||||
object Copy : TimelineItemAction("Copy", io.element.android.libraries.designsystem.VectorIcons.Copy)
|
||||
object Redact : TimelineItemAction("Redact", io.element.android.libraries.designsystem.VectorIcons.Delete, destructive = true)
|
||||
object Reply : TimelineItemAction("Reply", io.element.android.libraries.designsystem.VectorIcons.Reply)
|
||||
object Edit : TimelineItemAction("Edit", io.element.android.libraries.designsystem.VectorIcons.Edit)
|
||||
object Forward : TimelineItemAction("Forward", VectorIcons.ArrowForward)
|
||||
object Copy : TimelineItemAction("Copy", VectorIcons.Copy)
|
||||
object Redact : TimelineItemAction("Redact", VectorIcons.Delete, destructive = true)
|
||||
object Reply : TimelineItemAction("Reply", VectorIcons.Reply)
|
||||
object Edit : TimelineItemAction("Edit", VectorIcons.Edit)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.element.android.features.messages.textcomposer
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import io.element.android.libraries.designsystem.LocalIsDarkTheme
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import io.element.android.libraries.textcomposer.TextComposer
|
||||
|
||||
@Composable
|
||||
@@ -51,7 +51,7 @@ fun MessageComposerView(
|
||||
onComposerTextChange = ::onComposerTextChange,
|
||||
composerCanSendMessage = state.isSendButtonVisible,
|
||||
composerText = state.text?.charSequence?.toString(),
|
||||
isInDarkMode = LocalIsDarkTheme.current,
|
||||
isInDarkMode = !ElementTheme.colors.isLight,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
|
||||
@@ -39,11 +39,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDownward
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -79,6 +75,12 @@ import io.element.android.features.messages.timeline.model.content.TimelineItemT
|
||||
import io.element.android.features.messages.timeline.model.content.TimelineItemUnknownContent
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.PairCombinedPreviewParameter
|
||||
import io.element.android.libraries.matrix.core.EventId
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -355,19 +357,26 @@ class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
|
||||
TimelineItemGroupPositionProvider() to MessagesTimelineItemContentProvider()
|
||||
)
|
||||
|
||||
@Suppress("PreviewPublic")
|
||||
@Preview
|
||||
@Composable
|
||||
fun TimelineItemsPreview(
|
||||
@PreviewParameter(MessagesTimelineItemContentProvider::class)
|
||||
content: TimelineItemContent
|
||||
) {
|
||||
fun LoginRootScreenLightPreview(
|
||||
@PreviewParameter(MessagesTimelineItemContentProvider::class) content: TimelineItemContent
|
||||
) = ElementPreviewLight { ContentToPreview(content) }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LoginRootScreenDarkPreview(
|
||||
@PreviewParameter(MessagesTimelineItemContentProvider::class) content: TimelineItemContent
|
||||
) = ElementPreviewDark { ContentToPreview(content) }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(content: TimelineItemContent) {
|
||||
val timelineItems = persistentListOf(
|
||||
// 3 items (First Middle Last) with isMine = false
|
||||
createMessageEvent(
|
||||
isMine = false,
|
||||
content = content,
|
||||
groupPosition = MessagesItemGroupPosition.First
|
||||
groupPosition = MessagesItemGroupPosition.Last
|
||||
),
|
||||
createMessageEvent(
|
||||
isMine = false,
|
||||
@@ -377,13 +386,13 @@ fun TimelineItemsPreview(
|
||||
createMessageEvent(
|
||||
isMine = false,
|
||||
content = content,
|
||||
groupPosition = MessagesItemGroupPosition.Last
|
||||
groupPosition = MessagesItemGroupPosition.First
|
||||
),
|
||||
// 3 items (First Middle Last) with isMine = true
|
||||
createMessageEvent(
|
||||
isMine = true,
|
||||
content = content,
|
||||
groupPosition = MessagesItemGroupPosition.First
|
||||
groupPosition = MessagesItemGroupPosition.Last
|
||||
),
|
||||
createMessageEvent(
|
||||
isMine = true,
|
||||
@@ -393,7 +402,7 @@ fun TimelineItemsPreview(
|
||||
createMessageEvent(
|
||||
isMine = true,
|
||||
content = content,
|
||||
groupPosition = MessagesItemGroupPosition.Last
|
||||
groupPosition = MessagesItemGroupPosition.First
|
||||
),
|
||||
)
|
||||
TimelineView(
|
||||
|
||||
@@ -23,20 +23,14 @@ import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.features.messages.timeline.model.MessagesItemGroupPosition
|
||||
import io.element.android.libraries.designsystem.LocalIsDarkTheme
|
||||
import io.element.android.libraries.designsystem.MessageHighlightDark
|
||||
import io.element.android.libraries.designsystem.MessageHighlightLight
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Dark
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Light
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Dark
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Light
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
|
||||
private val BUBBLE_RADIUS = 16.dp
|
||||
|
||||
@@ -88,24 +82,12 @@ fun MessageEventBubble(
|
||||
}
|
||||
|
||||
val backgroundBubbleColor = if (isHighlighted) {
|
||||
if (LocalIsDarkTheme.current) {
|
||||
MessageHighlightDark
|
||||
} else {
|
||||
MessageHighlightLight
|
||||
}
|
||||
ElementTheme.colors.messageHighlightedBackground
|
||||
} else {
|
||||
if (isMine) {
|
||||
if (LocalIsDarkTheme.current) {
|
||||
SystemGrey5Dark
|
||||
} else {
|
||||
SystemGrey5Light
|
||||
}
|
||||
ElementTheme.colors.messageFromMeBackground
|
||||
} else {
|
||||
if (LocalIsDarkTheme.current) {
|
||||
SystemGrey6Dark
|
||||
} else {
|
||||
SystemGrey6Light
|
||||
}
|
||||
ElementTheme.colors.messageFromOtherBackground
|
||||
}
|
||||
}
|
||||
val bubbleShape = bubbleShape()
|
||||
|
||||
@@ -14,11 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalFoundationApi::class)
|
||||
|
||||
package io.element.android.features.messages.timeline.components
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
||||
@@ -20,16 +20,21 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
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.text.font.FontStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
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.Text
|
||||
|
||||
@Composable
|
||||
fun TimelineItemInformativeView(
|
||||
@@ -57,3 +62,20 @@ fun TimelineItemInformativeView(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserRowLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserRowDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
TimelineItemInformativeView(
|
||||
text = "Info",
|
||||
iconDescription = "",
|
||||
icon = Icons.Default.Delete
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CornerSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -34,6 +32,8 @@ import androidx.compose.ui.unit.sp
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import io.element.android.features.messages.timeline.model.AggregatedReaction
|
||||
import io.element.android.features.messages.timeline.model.TimelineItemReactions
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun TimelineItemReactionsView(
|
||||
|
||||
@@ -28,8 +28,6 @@ import androidx.compose.foundation.text.appendInlineContent
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
@@ -49,6 +47,8 @@ import androidx.compose.ui.unit.sp
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import io.element.android.libraries.designsystem.LinkColor
|
||||
import io.element.android.libraries.designsystem.components.ClickableLinkText
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.permalink.PermalinkData
|
||||
import io.element.android.libraries.matrix.permalink.PermalinkParser
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.features.onboarding
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
@@ -26,10 +24,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -49,7 +43,8 @@ import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.HorizontalPager
|
||||
import com.google.accompanist.pager.HorizontalPagerIndicator
|
||||
import com.google.accompanist.pager.rememberPagerState
|
||||
import io.element.android.libraries.designsystem.components.VectorButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -67,71 +62,55 @@ fun OnBoardingScreen(
|
||||
val carrouselState = remember { SplashCarouselStateFactory().create() }
|
||||
val nbOfPages = carrouselState.items.size
|
||||
var key by remember { mutableStateOf(false) }
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.padding(vertical = 16.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.padding(vertical = 16.dp)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
val pagerState = rememberPagerState()
|
||||
LaunchedEffect(key) {
|
||||
launch {
|
||||
delay(3_000)
|
||||
pagerState.animateScrollToPage((pagerState.currentPage + 1) % nbOfPages)
|
||||
// https://stackoverflow.com/questions/73714228/accompanist-pager-animatescrolltopage-doesnt-scroll-to-next-page-correctly
|
||||
key = !key
|
||||
}
|
||||
}
|
||||
LaunchedEffect(pagerState) {
|
||||
// Collect from the pager state a snapshotFlow reading the currentPage
|
||||
snapshotFlow { pagerState.currentPage }.collect { page ->
|
||||
onPageChanged(page)
|
||||
}
|
||||
}
|
||||
HorizontalPager(
|
||||
modifier = Modifier.weight(1f),
|
||||
count = nbOfPages,
|
||||
state = pagerState,
|
||||
) { page ->
|
||||
// Our page content
|
||||
OnBoardingPage(carrouselState.items[page])
|
||||
}
|
||||
HorizontalPagerIndicator(
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
.align(CenterHorizontally)
|
||||
.padding(16.dp),
|
||||
)
|
||||
Button(
|
||||
onClick = {
|
||||
onSignIn()
|
||||
},
|
||||
enabled = true,
|
||||
modifier = Modifier
|
||||
.align(CenterHorizontally)
|
||||
.testTag(TestTags.onBoardingSignIn)
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
val pagerState = rememberPagerState()
|
||||
LaunchedEffect(key) {
|
||||
launch {
|
||||
delay(3_000)
|
||||
pagerState.animateScrollToPage((pagerState.currentPage + 1) % nbOfPages)
|
||||
// https://stackoverflow.com/questions/73714228/accompanist-pager-animatescrolltopage-doesnt-scroll-to-next-page-correctly
|
||||
key = !key
|
||||
}
|
||||
}
|
||||
LaunchedEffect(pagerState) {
|
||||
// Collect from the pager state a snapshotFlow reading the currentPage
|
||||
snapshotFlow { pagerState.currentPage }.collect { page ->
|
||||
onPageChanged(page)
|
||||
}
|
||||
}
|
||||
HorizontalPager(
|
||||
modifier = Modifier.weight(1f),
|
||||
count = nbOfPages,
|
||||
state = pagerState,
|
||||
) { page ->
|
||||
// Our page content
|
||||
OnBoardingPage(carrouselState.items[page])
|
||||
}
|
||||
HorizontalPagerIndicator(
|
||||
pagerState = pagerState,
|
||||
modifier = Modifier
|
||||
.align(CenterHorizontally)
|
||||
.padding(16.dp),
|
||||
)
|
||||
/*
|
||||
VectorButton(
|
||||
text = "CREATE ACCOUNT",
|
||||
onClick = {
|
||||
onSignUp()
|
||||
},
|
||||
enabled = true,
|
||||
modifier = Modifier
|
||||
.align(CenterHorizontally)
|
||||
.padding(top = 16.dp)
|
||||
)
|
||||
*/
|
||||
VectorButton(
|
||||
text = stringResource(id = StringR.string.login_splash_submit),
|
||||
onClick = {
|
||||
onSignIn()
|
||||
},
|
||||
enabled = true,
|
||||
modifier = Modifier
|
||||
.align(CenterHorizontally)
|
||||
.testTag(TestTags.onBoardingSignIn)
|
||||
.padding(top = 16.dp)
|
||||
)
|
||||
Text(text = stringResource(id = StringR.string.login_splash_submit))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import io.element.android.features.rageshake.preferences.RageshakePreferencesSta
|
||||
import io.element.android.features.rageshake.preferences.RageshakePreferencesView
|
||||
import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceView
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -56,7 +58,14 @@ fun PreferencesRootView(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferencesContentPreview() {
|
||||
fun PreferencesRootViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferencesRootViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
val state = PreferencesRootState(
|
||||
logoutState = LogoutPreferenceState(),
|
||||
rageshakeState = RageshakePreferencesState(),
|
||||
|
||||
@@ -26,13 +26,7 @@ import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
@@ -54,10 +48,15 @@ import io.element.android.libraries.architecture.Async
|
||||
import io.element.android.libraries.designsystem.components.LabelledCheckbox
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.OutlinedTextField
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun BugReportView(
|
||||
state: BugReportState,
|
||||
@@ -73,147 +72,151 @@ fun BugReportView(
|
||||
}
|
||||
return
|
||||
}
|
||||
Surface(
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
) {
|
||||
Box(
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.systemBarsPadding()
|
||||
.imePadding()
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
val isError = state.sending is Async.Failure
|
||||
val isFormEnabled = state.sending !is Async.Loading
|
||||
// Title
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.send_bug_report),
|
||||
modifier = Modifier
|
||||
.verticalScroll(
|
||||
state = scrollState,
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
// Form
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.send_bug_report_description),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
fontSize = 16.sp,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
var descriptionFieldState by textFieldState(
|
||||
stateValue = state.formState.description
|
||||
)
|
||||
Column(
|
||||
// modifier = Modifier.weight(1f),
|
||||
) {
|
||||
val isError = state.sending is Async.Failure
|
||||
val isFormEnabled = state.sending !is Async.Loading
|
||||
// Title
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.send_bug_report),
|
||||
OutlinedTextField(
|
||||
value = descriptionFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
textAlign = TextAlign.Center,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
)
|
||||
// Form
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.send_bug_report_description),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||
fontSize = 16.sp,
|
||||
)
|
||||
var descriptionFieldState by textFieldState(
|
||||
stateValue = state.formState.description
|
||||
)
|
||||
Column(
|
||||
// modifier = Modifier.weight(1f),
|
||||
) {
|
||||
OutlinedTextField(
|
||||
value = descriptionFieldState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp),
|
||||
enabled = isFormEnabled,
|
||||
label = {
|
||||
Text(text = stringResource(id = StringR.string.send_bug_report_placeholder))
|
||||
},
|
||||
supportingText = {
|
||||
Text(text = stringResource(id = StringR.string.send_bug_report_description_in_english))
|
||||
},
|
||||
onValueChange = {
|
||||
descriptionFieldState = it
|
||||
eventSink(BugReportEvents.SetDescription(it))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Next
|
||||
),
|
||||
// TODO Error text too short
|
||||
)
|
||||
}
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.sendLogs,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) },
|
||||
.padding(top = 16.dp),
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_logs)
|
||||
label = {
|
||||
Text(text = stringResource(id = StringR.string.send_bug_report_placeholder))
|
||||
},
|
||||
supportingText = {
|
||||
Text(text = stringResource(id = StringR.string.send_bug_report_description_in_english))
|
||||
},
|
||||
onValueChange = {
|
||||
descriptionFieldState = it
|
||||
eventSink(BugReportEvents.SetDescription(it))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Next
|
||||
),
|
||||
// TODO Error text too short
|
||||
)
|
||||
if (state.hasCrashLogs) {
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.sendCrashLogs,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendCrashLog(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_crash_logs)
|
||||
)
|
||||
}
|
||||
}
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.sendLogs,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_logs)
|
||||
)
|
||||
if (state.hasCrashLogs) {
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.canContact,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetCanContact(it)) },
|
||||
checked = state.formState.sendCrashLogs,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendCrashLog(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.you_may_contact_me)
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_crash_logs)
|
||||
)
|
||||
if (state.screenshotUri != null) {
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.sendScreenshot,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendScreenshot(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_screenshot)
|
||||
)
|
||||
if (state.formState.sendScreenshot) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val model = ImageRequest.Builder(context)
|
||||
.data(state.screenshotUri)
|
||||
.build()
|
||||
AsyncImage(
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.5f),
|
||||
model = model,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.canContact,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetCanContact(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.you_may_contact_me)
|
||||
)
|
||||
if (state.screenshotUri != null) {
|
||||
LabelledCheckbox(
|
||||
checked = state.formState.sendScreenshot,
|
||||
onCheckedChange = { eventSink(BugReportEvents.SetSendScreenshot(it)) },
|
||||
enabled = isFormEnabled,
|
||||
text = stringResource(id = StringR.string.send_bug_report_include_screenshot)
|
||||
)
|
||||
if (state.formState.sendScreenshot) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val model = ImageRequest.Builder(context)
|
||||
.data(state.screenshotUri)
|
||||
.build()
|
||||
AsyncImage(
|
||||
modifier = Modifier.fillMaxWidth(fraction = 0.5f),
|
||||
model = model,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
// Submit
|
||||
Button(
|
||||
onClick = { eventSink(BugReportEvents.SendBugReport) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 32.dp)
|
||||
) {
|
||||
Text(text = stringResource(id = StringR.string.action_send))
|
||||
}
|
||||
}
|
||||
when (state.sending) {
|
||||
is Async.Loading -> {
|
||||
CircularProgressIndicator(
|
||||
progress = state.sendingProgress,
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
}
|
||||
is Async.Failure -> ErrorDialog(
|
||||
content = state.sending.error.toString(),
|
||||
// Submit
|
||||
Button(
|
||||
onClick = { eventSink(BugReportEvents.SendBugReport) },
|
||||
enabled = state.submitEnabled,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 32.dp)
|
||||
) {
|
||||
Text(text = stringResource(id = StringR.string.action_send))
|
||||
}
|
||||
}
|
||||
when (state.sending) {
|
||||
is Async.Loading -> {
|
||||
CircularProgressIndicator(
|
||||
progress = state.sendingProgress,
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
is Async.Failure -> ErrorDialog(
|
||||
content = state.sending.error.toString(),
|
||||
)
|
||||
else -> Unit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun BugReportContentPreview() {
|
||||
@Composable
|
||||
fun BugReportViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BugReportViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
BugReportView(
|
||||
state = BugReportState(),
|
||||
)
|
||||
|
||||
@@ -20,6 +20,8 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@@ -67,7 +69,14 @@ fun CrashDetectionContent(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CrashDetectionContentPreview() {
|
||||
fun CrashDetectionContentLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CrashDetectionContentDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
CrashDetectionContent(
|
||||
state = CrashDetectionState()
|
||||
)
|
||||
|
||||
@@ -27,6 +27,8 @@ import io.element.android.features.rageshake.screenshot.ImageResult
|
||||
import io.element.android.features.rageshake.screenshot.screenshot
|
||||
import io.element.android.libraries.androidutils.hardware.vibrate
|
||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
@@ -99,6 +101,13 @@ fun RageshakeDialogContent(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RageshakeDialogContentPreview() {
|
||||
fun RageshakeDialogContentLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RageshakeDialogContentDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
RageshakeDialogContent()
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import io.element.android.libraries.designsystem.components.preferences.Preferen
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSlide
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceSwitch
|
||||
import io.element.android.libraries.designsystem.components.preferences.PreferenceText
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -73,14 +75,28 @@ fun RageshakePreferencesView(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun RageshakePreferencesViewPreview() {
|
||||
@Composable
|
||||
fun RageshakePreferencesViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RageshakePreferencesViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
RageshakePreferencesView(RageshakePreferencesState(isEnabled = true, isSupported = true, sensitivity = 0.5f))
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun RageshakePreferenceNotSupportedPreview() {
|
||||
@Composable
|
||||
fun RageshakePreferencesViewNotSupportedLightPreview() = ElementPreviewLight { ContentNotSupportedToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RageshakePreferencesViewNotSupportedDarkPreview() = ElementPreviewDark { ContentNotSupportedToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentNotSupportedToPreview() {
|
||||
RageshakePreferencesView(RageshakePreferencesState(isEnabled = true, isSupported = false, sensitivity = 0.5f))
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.features.roomlist
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -24,7 +22,6 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -43,6 +40,9 @@ import io.element.android.features.roomlist.model.RoomListRoomSummary
|
||||
import io.element.android.features.roomlist.model.RoomListState
|
||||
import io.element.android.features.roomlist.model.stubbedRoomSummaries
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.core.RoomId
|
||||
import io.element.android.libraries.matrix.core.UserId
|
||||
@@ -76,6 +76,7 @@ fun RoomListView(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RoomListView(
|
||||
roomSummaries: ImmutableList<RoomListRoomSummary>,
|
||||
@@ -125,11 +126,15 @@ fun RoomListView(
|
||||
filter = filter,
|
||||
onFilterChanged = onFilterChanged,
|
||||
onOpenSettings = onOpenSettings,
|
||||
scrollBehavior = scrollBehavior
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = Modifier,
|
||||
)
|
||||
},
|
||||
content = { padding ->
|
||||
Column(modifier = Modifier.padding(padding)) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(padding)
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
@@ -152,7 +157,14 @@ private fun RoomListRoomSummary.contentType() = isPlaceholder
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RoomListViewPreview() {
|
||||
fun RoomListViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun RoomListViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
RoomListView(
|
||||
roomSummaries = stubbedRoomSummaries(),
|
||||
matrixUser = MatrixUser(id = UserId("@id"), username = "User#1", avatarData = AvatarData("U")),
|
||||
|
||||
@@ -27,14 +27,7 @@ import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.MediumTopAppBar
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -46,7 +39,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
@@ -54,6 +46,12 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
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.MediumTopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextField
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
@@ -64,7 +62,8 @@ fun RoomListTopBar(
|
||||
filter: String,
|
||||
onFilterChanged: (String) -> Unit,
|
||||
onOpenSettings: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
LogCompositions(
|
||||
tag = "RoomListScreen",
|
||||
@@ -87,6 +86,7 @@ fun RoomListTopBar(
|
||||
onFilterChanged = onFilterChanged,
|
||||
onCloseClicked = ::closeFilter,
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
DefaultRoomListTopBar(
|
||||
@@ -96,6 +96,7 @@ fun RoomListTopBar(
|
||||
searchWidgetStateIsOpened = true
|
||||
},
|
||||
scrollBehavior = scrollBehavior,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -148,14 +149,6 @@ fun SearchRoomListTopBar(
|
||||
}
|
||||
}
|
||||
},
|
||||
colors = TextFieldDefaults.textFieldColors(
|
||||
textColor = MaterialTheme.colorScheme.onBackground,
|
||||
containerColor = Color.Transparent,
|
||||
cursorColor = MaterialTheme.colorScheme.onBackground.copy(alpha = ContentAlpha.medium),
|
||||
focusedIndicatorColor = Color.Transparent,
|
||||
unfocusedIndicatorColor = Color.Transparent,
|
||||
disabledIndicatorColor = Color.Transparent
|
||||
)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
@@ -182,10 +175,11 @@ private fun DefaultRoomListTopBar(
|
||||
matrixUser: MatrixUser?,
|
||||
onOpenSettings: () -> Unit,
|
||||
onSearchClicked: () -> Unit,
|
||||
scrollBehavior: TopAppBarScrollBehavior
|
||||
scrollBehavior: TopAppBarScrollBehavior,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
MediumTopAppBar(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
title = {
|
||||
Text(
|
||||
|
||||
@@ -32,7 +32,6 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -54,6 +53,13 @@ import androidx.compose.ui.unit.sp
|
||||
import com.google.accompanist.placeholder.material.placeholder
|
||||
import io.element.android.features.roomlist.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.roomListPlaceHolder
|
||||
import io.element.android.libraries.designsystem.theme.roomListRoomMessage
|
||||
import io.element.android.libraries.designsystem.theme.roomListRoomMessageDate
|
||||
import io.element.android.libraries.designsystem.theme.roomListRoomName
|
||||
import io.element.android.libraries.designsystem.theme.roomListUnreadIndicator
|
||||
|
||||
private val minHeight = 72.dp
|
||||
|
||||
@@ -95,7 +101,11 @@ internal fun DefaultRoomSummaryRow(
|
||||
) {
|
||||
Avatar(
|
||||
room.avatarData,
|
||||
modifier = Modifier.placeholder(room.isPlaceholder, shape = CircleShape)
|
||||
modifier = Modifier.placeholder(
|
||||
visible = room.isPlaceholder,
|
||||
shape = CircleShape,
|
||||
color = ElementTheme.colors.roomListPlaceHolder(),
|
||||
)
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@@ -105,19 +115,27 @@ internal fun DefaultRoomSummaryRow(
|
||||
) {
|
||||
// Name
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.placeholder(room.isPlaceholder, shape = TextPlaceholderShape),
|
||||
modifier = Modifier.placeholder(
|
||||
visible = room.isPlaceholder,
|
||||
shape = TextPlaceholderShape,
|
||||
color = ElementTheme.colors.roomListPlaceHolder(),
|
||||
),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
text = room.name,
|
||||
color = MaterialTheme.roomListRoomName(),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
// Last Message
|
||||
Text(
|
||||
modifier = Modifier.placeholder(room.isPlaceholder, shape = TextPlaceholderShape),
|
||||
modifier = Modifier.placeholder(
|
||||
visible = room.isPlaceholder,
|
||||
shape = TextPlaceholderShape,
|
||||
color = ElementTheme.colors.roomListPlaceHolder(),
|
||||
),
|
||||
text = room.lastMessage?.toString().orEmpty(),
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
color = MaterialTheme.roomListRoomMessage(),
|
||||
fontSize = 14.sp,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
@@ -129,14 +147,18 @@ internal fun DefaultRoomSummaryRow(
|
||||
.alignByBaseline(),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.placeholder(room.isPlaceholder, shape = TextPlaceholderShape),
|
||||
modifier = Modifier.placeholder(
|
||||
visible = room.isPlaceholder,
|
||||
shape = TextPlaceholderShape,
|
||||
color = ElementTheme.colors.roomListPlaceHolder(),
|
||||
),
|
||||
fontSize = 12.sp,
|
||||
text = room.timestamp ?: "",
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
color = MaterialTheme.roomListRoomMessageDate(),
|
||||
)
|
||||
Spacer(Modifier.size(4.dp))
|
||||
val unreadIndicatorColor =
|
||||
if (room.hasUnread) MaterialTheme.colorScheme.primary else Color.Transparent
|
||||
if (room.hasUnread) MaterialTheme.roomListUnreadIndicator() else Color.Transparent
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(12.dp)
|
||||
|
||||
@@ -17,11 +17,14 @@
|
||||
package io.element.android.features.template
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun TemplateView(
|
||||
@@ -29,13 +32,23 @@ fun TemplateView(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Box(modifier, contentAlignment = Alignment.Center) {
|
||||
Text("Template feature view")
|
||||
Text(
|
||||
"Template feature view",
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun TemplateViewPreview() {
|
||||
@Composable
|
||||
fun TemplateViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TemplateViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
TemplateView(
|
||||
state = TemplateState(),
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ ksp = "1.8.0-1.0.8"
|
||||
molecule = "0.7.0"
|
||||
|
||||
# AndroidX
|
||||
material = "1.6.1"
|
||||
material = "1.8.0"
|
||||
corektx = "1.9.0"
|
||||
datastore = "1.0.0"
|
||||
constraintlayout = "2.1.4"
|
||||
|
||||
@@ -52,10 +52,4 @@ val ElementGreen = Color(0xFF0DBD8B)
|
||||
val ElementOrange = Color(0xFFD9B072)
|
||||
val Vermilion = Color(0xFFFF5B55)
|
||||
|
||||
// TODO Update color
|
||||
val MessageHighlightLight = Azure
|
||||
|
||||
// TODO Update color
|
||||
val MessageHighlightDark = Azure
|
||||
|
||||
val LinkColor = Color(0xFF054F6E)
|
||||
|
||||
@@ -25,6 +25,6 @@ fun Boolean.toEnabledColor(): Color {
|
||||
return if (this) {
|
||||
MaterialTheme.colorScheme.primary
|
||||
} else {
|
||||
MaterialTheme.colorScheme.secondary
|
||||
MaterialTheme.colorScheme.primary.copy(alpha = 0.40f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,55 +16,13 @@
|
||||
|
||||
package io.element.android.libraries.designsystem
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.airbnb.android.showkase.annotation.ShowkaseTypography
|
||||
|
||||
@ShowkaseTypography(name = "Body Large", group = "Element")
|
||||
val bodyLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Headline Small", group = "Element")
|
||||
val headlineSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 32.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val Typography = Typography(
|
||||
bodyLarge = bodyLarge,
|
||||
headlineSmall = headlineSmall,
|
||||
/* Other default text styles to override
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.sp
|
||||
),
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 11.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
*/
|
||||
)
|
||||
|
||||
// TODO Remove
|
||||
object ElementTextStyles {
|
||||
|
||||
object Bold {
|
||||
@@ -21,7 +21,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
@@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalUriHandler
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
||||
@@ -83,6 +84,7 @@ fun ClickableLinkText(
|
||||
onTextLayout = {
|
||||
layoutResult.value = it
|
||||
},
|
||||
inlineContent = inlineContent
|
||||
inlineContent = inlineContent,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,12 +18,15 @@ package io.element.android.libraries.designsystem.components
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun LabelledCheckbox(
|
||||
@@ -42,13 +45,23 @@ fun LabelledCheckbox(
|
||||
onCheckedChange = onCheckedChange,
|
||||
enabled = enabled,
|
||||
)
|
||||
Text(text = text)
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LabelledCheckboxPreview() {
|
||||
fun LabelledCheckboxLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun LabelledCheckboxDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
LabelledCheckbox(
|
||||
checked = true,
|
||||
text = "Some text",
|
||||
|
||||
@@ -22,9 +22,7 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -32,6 +30,10 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun ProgressDialog(
|
||||
@@ -48,19 +50,19 @@ fun ProgressDialog(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
shape = RoundedCornerShape(8.dp)
|
||||
)
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.padding(16.dp),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
if (!text.isNullOrBlank()) {
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
}
|
||||
@@ -69,8 +71,15 @@ fun ProgressDialog(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ProgressDialogPreview() {
|
||||
@Composable
|
||||
fun ProgressDialogLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ProgressDialogDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ProgressDialog(text = "test dialog content")
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package io.element.android.libraries.designsystem.components
|
||||
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -29,7 +28,7 @@ fun VectorIcon(
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = LocalContentColor.current,
|
||||
) {
|
||||
Icon(
|
||||
androidx.compose.material3.Icon(
|
||||
painter = painterResource(id = resourceId),
|
||||
contentDescription = null,
|
||||
modifier = modifier,
|
||||
|
||||
@@ -20,7 +20,6 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -34,6 +33,9 @@ import androidx.compose.ui.unit.sp
|
||||
import coil.compose.AsyncImage
|
||||
import io.element.android.libraries.designsystem.AvatarGradientEnd
|
||||
import io.element.android.libraries.designsystem.AvatarGradientStart
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import timber.log.Timber
|
||||
|
||||
@Composable
|
||||
@@ -97,6 +99,13 @@ private fun InitialsAvatar(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun InitialsAvatarPreview() {
|
||||
fun AvatarLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AvatarDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Avatar(AvatarData(name = "A"))
|
||||
}
|
||||
|
||||
@@ -22,13 +22,20 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
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.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
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.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -43,6 +50,12 @@ fun ConfirmationDialog(
|
||||
onCancelClicked: () -> Unit = {},
|
||||
onThirdButtonClicked: () -> Unit = {},
|
||||
onDismiss: () -> Unit = {},
|
||||
shape: Shape = AlertDialogDefaults.shape,
|
||||
containerColor: Color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
iconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
titleContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
|
||||
) {
|
||||
AlertDialog(
|
||||
modifier = modifier,
|
||||
@@ -93,12 +106,25 @@ fun ConfirmationDialog(
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = shape,
|
||||
containerColor = containerColor,
|
||||
iconContentColor = iconContentColor,
|
||||
titleContentColor = titleContentColor,
|
||||
textContentColor = textContentColor,
|
||||
tonalElevation = tonalElevation,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ConfirmationDialogPreview() {
|
||||
@Composable
|
||||
fun ConfirmationDialogLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ConfirmationDialogDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ConfirmationDialog(
|
||||
title = "Title",
|
||||
content = "Content",
|
||||
|
||||
@@ -21,13 +21,20 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
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.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
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.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -37,6 +44,12 @@ fun ErrorDialog(
|
||||
title: String = stringResource(id = StringR.string.dialog_title_error),
|
||||
submitText: String = stringResource(id = StringR.string.ok),
|
||||
onDismiss: () -> Unit = {},
|
||||
shape: Shape = AlertDialogDefaults.shape,
|
||||
containerColor: Color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
iconContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
titleContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textContentColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
tonalElevation: Dp = AlertDialogDefaults.TonalElevation,
|
||||
) {
|
||||
AlertDialog(
|
||||
modifier = modifier,
|
||||
@@ -62,12 +75,25 @@ fun ErrorDialog(
|
||||
}
|
||||
}
|
||||
},
|
||||
shape = shape,
|
||||
containerColor = containerColor,
|
||||
iconContentColor = iconContentColor,
|
||||
titleContentColor = titleContentColor,
|
||||
textContentColor = textContentColor,
|
||||
tonalElevation = tonalElevation,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun ErrorDialogPreview() {
|
||||
@Composable
|
||||
fun ErrorDialogLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ErrorDialogDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ErrorDialog(
|
||||
content = "Content",
|
||||
)
|
||||
|
||||
@@ -20,13 +20,18 @@ import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Divider
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Announcement
|
||||
import androidx.compose.material.icons.filled.BugReport
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
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.Divider
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun PreferenceCategory(
|
||||
@@ -46,20 +51,39 @@ fun PreferenceCategory(
|
||||
Text(
|
||||
modifier = Modifier.padding(top = 8.dp, start = 56.dp),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
text = title
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
text = title,
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreferenceCategoryPreview() {
|
||||
@Composable
|
||||
fun PreferenceCategoryLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferenceCategoryDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
PreferenceCategory(
|
||||
title = "Category title",
|
||||
) {
|
||||
PreferenceTextPreview()
|
||||
PreferenceSwitchPreview()
|
||||
PreferenceSlidePreview()
|
||||
PreferenceText(
|
||||
title = "Title",
|
||||
icon = Icons.Default.BugReport,
|
||||
)
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
icon = Icons.Default.Announcement,
|
||||
isChecked = true
|
||||
)
|
||||
PreferenceSlide(
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
value = 0.75F
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,10 @@ import androidx.compose.foundation.layout.systemBarsPadding
|
||||
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.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -42,6 +39,13 @@ 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.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
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -110,12 +114,36 @@ fun PreferenceTopAppBar(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreferenceScreenPreview() {
|
||||
@Composable
|
||||
fun PreferenceViewLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferenceViewDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
PreferenceView(
|
||||
title = "Preference screen"
|
||||
) {
|
||||
PreferenceCategoryPreview()
|
||||
PreferenceCategory(
|
||||
title = "Category title",
|
||||
) {
|
||||
PreferenceText(
|
||||
title = "Title",
|
||||
icon = Icons.Default.BugReport,
|
||||
)
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
icon = Icons.Default.Announcement,
|
||||
isChecked = true
|
||||
)
|
||||
PreferenceSlide(
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
value = 0.75F
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,14 +24,16 @@ import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
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
|
||||
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
|
||||
import io.element.android.libraries.designsystem.theme.components.Slider
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
|
||||
@Composable
|
||||
@@ -84,9 +86,16 @@ fun PreferenceSlide(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreferenceSlidePreview() {
|
||||
@Composable
|
||||
fun PreferenceSlideLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferenceSlideDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
PreferenceSlide(
|
||||
title = "Slide",
|
||||
summary = "Summary",
|
||||
|
||||
@@ -24,15 +24,17 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Announcement
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
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
|
||||
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
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
|
||||
@Composable
|
||||
@@ -75,12 +77,20 @@ fun PreferenceSwitch(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreferenceSwitchPreview() {
|
||||
@Composable
|
||||
fun PreferenceSwitchLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferenceSwitchDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
PreferenceSwitch(
|
||||
title = "Switch",
|
||||
icon = Icons.Default.Announcement,
|
||||
enabled = true,
|
||||
isChecked = true
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,13 +25,15 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.BugReport
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
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
|
||||
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
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
|
||||
@Composable
|
||||
fun PreferenceText(
|
||||
@@ -57,15 +59,23 @@ fun PreferenceText(
|
||||
.weight(1f)
|
||||
.padding(end = preferencePaddingEnd),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
text = title
|
||||
text = title,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
fun PreferenceTextPreview() {
|
||||
@Composable
|
||||
fun PreferenceTextLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreferenceTextDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
PreferenceText(
|
||||
title = "Title",
|
||||
icon = Icons.Default.BugReport,
|
||||
|
||||
@@ -19,11 +19,11 @@ package io.element.android.libraries.designsystem.components.preferences.compone
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.toEnabledColor
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.preview
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewLight(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = false,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ElementPreviewDark(
|
||||
showBackground: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementPreview(
|
||||
darkTheme = true,
|
||||
showBackground = showBackground,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ElementPreview(
|
||||
darkTheme: Boolean,
|
||||
showBackground: Boolean,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
ElementTheme(darkTheme = darkTheme) {
|
||||
if (showBackground) {
|
||||
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||
content()
|
||||
}
|
||||
} else {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.theme
|
||||
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.SystemGrey4Dark
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Light
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.previews.ColorListPreview
|
||||
|
||||
/**
|
||||
* Room list.
|
||||
*/
|
||||
@Composable
|
||||
fun MaterialTheme.roomListRoomName() = colorScheme.primary
|
||||
|
||||
@Composable
|
||||
fun MaterialTheme.roomListRoomMessage() = colorScheme.secondary
|
||||
|
||||
@Composable
|
||||
fun MaterialTheme.roomListRoomMessageDate() = colorScheme.secondary
|
||||
|
||||
@Composable
|
||||
fun MaterialTheme.roomListUnreadIndicator() = colorScheme.primary
|
||||
|
||||
@Composable
|
||||
fun ElementColors.roomListPlaceHolder() = if (isLight) SystemGrey6Light else SystemGrey4Dark
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ColorAliasesLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ColorAliasesDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ColorListPreview(
|
||||
backgroundColor = Color.Black,
|
||||
foregroundColor = Color.White,
|
||||
colors = mapOf(
|
||||
"roomListRoomName" to MaterialTheme.roomListRoomName(),
|
||||
"roomListRoomMessage" to MaterialTheme.roomListRoomMessage(),
|
||||
"roomListRoomMessageDate" to MaterialTheme.roomListRoomMessageDate(),
|
||||
"roomListUnreadIndicator" to MaterialTheme.roomListUnreadIndicator(),
|
||||
"roomListPlaceHolder" to ElementTheme.colors.roomListPlaceHolder(),
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.theme
|
||||
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.Azure
|
||||
import io.element.android.libraries.designsystem.DarkGrey
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Dark
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Dark
|
||||
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
|
||||
|
||||
fun elementColorsDark() = ElementColors(
|
||||
messageFromMeBackground = SystemGrey5Dark,
|
||||
messageFromOtherBackground = SystemGrey6Dark,
|
||||
messageHighlightedBackground = Azure,
|
||||
isLight = false,
|
||||
)
|
||||
|
||||
// TODO Lots of colors are missing
|
||||
val materialColorSchemeDark = darkColorScheme(
|
||||
primary = Color.White,
|
||||
// TODO onPrimary = ColorDarkTokens.OnPrimary,
|
||||
// TODO primaryContainer = ColorDarkTokens.PrimaryContainer,
|
||||
// TODO onPrimaryContainer = ColorDarkTokens.OnPrimaryContainer,
|
||||
// TODO inversePrimary = ColorDarkTokens.InversePrimary,
|
||||
secondary = DarkGrey,
|
||||
// TODO onSecondary = ColorDarkTokens.OnSecondary,
|
||||
// TODO secondaryContainer = ColorDarkTokens.SecondaryContainer,
|
||||
// TODO onSecondaryContainer = ColorDarkTokens.OnSecondaryContainer,
|
||||
tertiary = Color.White,
|
||||
// TODO onTertiary = ColorDarkTokens.OnTertiary,
|
||||
// TODO tertiaryContainer = ColorDarkTokens.TertiaryContainer,
|
||||
// TODO onTertiaryContainer = ColorDarkTokens.OnTertiaryContainer,
|
||||
background = Color.Black,
|
||||
onBackground = Color.White,
|
||||
surface = Color.Black,
|
||||
onSurface = Color.White,
|
||||
surfaceVariant = SystemGrey5Dark,
|
||||
// TODO onSurfaceVariant = ColorDarkTokens.OnSurfaceVariant,
|
||||
// TODO surfaceTint = primary,
|
||||
// TODO inverseSurface = ColorDarkTokens.InverseSurface,
|
||||
// TODO inverseOnSurface = ColorDarkTokens.InverseOnSurface,
|
||||
// TODO error = ColorDarkTokens.Error,
|
||||
// TODO onError = ColorDarkTokens.OnError,
|
||||
// TODO errorContainer = ColorDarkTokens.ErrorContainer,
|
||||
// TODO onErrorContainer = ColorDarkTokens.OnErrorContainer,
|
||||
// TODO outline = ColorDarkTokens.Outline,
|
||||
// TODO outlineVariant = ColorDarkTokens.OutlineVariant,
|
||||
// TODO scrim = ColorDarkTokens.Scrim,
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ColorsSchemePreviewDark() = ColorsSchemePreview(
|
||||
Color.White,
|
||||
Color.Black,
|
||||
materialColorSchemeDark,
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.theme
|
||||
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.Azure
|
||||
import io.element.android.libraries.designsystem.LightGrey
|
||||
import io.element.android.libraries.designsystem.SystemGrey5Light
|
||||
import io.element.android.libraries.designsystem.SystemGrey6Light
|
||||
import io.element.android.libraries.designsystem.theme.previews.ColorsSchemePreview
|
||||
|
||||
fun elementColorsLight() = ElementColors(
|
||||
messageFromMeBackground = SystemGrey5Light,
|
||||
messageFromOtherBackground = SystemGrey6Light,
|
||||
messageHighlightedBackground = Azure,
|
||||
isLight = true,
|
||||
)
|
||||
|
||||
// TODO Lots of colors are missing
|
||||
val materialColorSchemeLight = lightColorScheme(
|
||||
primary = Color.Black,
|
||||
// TODO onPrimary = ColorLightTokens.OnPrimary,
|
||||
// TODO primaryContainer = ColorLightTokens.PrimaryContainer,
|
||||
// TODO onPrimaryContainer = ColorLightTokens.OnPrimaryContainer,
|
||||
// TODO inversePrimary = ColorLightTokens.InversePrimary,
|
||||
secondary = LightGrey,
|
||||
// TODO onSecondary = ColorLightTokens.OnSecondary,
|
||||
// TODO secondaryContainer = ColorLightTokens.SecondaryContainer,
|
||||
// TODO onSecondaryContainer = ColorLightTokens.OnSecondaryContainer,
|
||||
tertiary = Color.Black,
|
||||
// TODO onTertiary = ColorLightTokens.OnTertiary,
|
||||
// TODO tertiaryContainer = ColorLightTokens.TertiaryContainer,
|
||||
// TODO onTertiaryContainer = ColorLightTokens.OnTertiaryContainer,
|
||||
background = Color.White,
|
||||
onBackground = Color.Black,
|
||||
surface = Color.White,
|
||||
onSurface = Color.Black,
|
||||
surfaceVariant = SystemGrey5Light,
|
||||
onSurfaceVariant = Color.Black,
|
||||
// TODO surfaceTint = primary,
|
||||
// TODO inverseSurface = ColorLightTokens.InverseSurface,
|
||||
// TODO inverseOnSurface = ColorLightTokens.InverseOnSurface,
|
||||
// TODO error = ColorLightTokens.Error,
|
||||
// TODO onError = ColorLightTokens.OnError,
|
||||
// TODO errorContainer = ColorLightTokens.ErrorContainer,
|
||||
// TODO onErrorContainer = ColorLightTokens.OnErrorContainer,
|
||||
// TODO outline = ColorLightTokens.Outline,
|
||||
// TODO outlineVariant = ColorLightTokens.OutlineVariant,
|
||||
// TODO scrim = ColorLightTokens.Scrim,
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ColorsSchemePreviewLight() = ColorsSchemePreview(
|
||||
Color.Black,
|
||||
Color.White,
|
||||
materialColorSchemeLight,
|
||||
)
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.theme
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
class ElementColors(
|
||||
messageFromMeBackground: Color,
|
||||
messageFromOtherBackground: Color,
|
||||
messageHighlightedBackground: Color,
|
||||
isLight: Boolean,
|
||||
) {
|
||||
var messageFromMeBackground by mutableStateOf(messageFromMeBackground)
|
||||
private set
|
||||
var messageFromOtherBackground by mutableStateOf(messageFromOtherBackground)
|
||||
private set
|
||||
var messageHighlightedBackground by mutableStateOf(messageHighlightedBackground)
|
||||
private set
|
||||
|
||||
var isLight by mutableStateOf(isLight)
|
||||
private set
|
||||
|
||||
fun copy(
|
||||
messageFromMeBackground: Color = this.messageFromMeBackground,
|
||||
messageFromOtherBackground: Color = this.messageFromOtherBackground,
|
||||
messageHighlightedBackground: Color = this.messageHighlightedBackground,
|
||||
isLight: Boolean = this.isLight,
|
||||
) = ElementColors(
|
||||
messageFromMeBackground = messageFromMeBackground,
|
||||
messageFromOtherBackground = messageFromOtherBackground,
|
||||
messageHighlightedBackground = messageHighlightedBackground,
|
||||
isLight = isLight,
|
||||
)
|
||||
|
||||
fun updateColorsFrom(other: ElementColors) {
|
||||
messageFromMeBackground = other.messageFromMeBackground
|
||||
messageFromOtherBackground = other.messageFromOtherBackground
|
||||
messageHighlightedBackground = other.messageHighlightedBackground
|
||||
isLight = other.isLight
|
||||
}
|
||||
}
|
||||
@@ -14,77 +14,58 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem
|
||||
package io.element.android.libraries.designsystem.theme
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
|
||||
private val DarkColorScheme = darkColorScheme(
|
||||
primary = Color.White,
|
||||
secondary = DarkGrey,
|
||||
tertiary = Color.White,
|
||||
background = Color.Black,
|
||||
onBackground = Color.White,
|
||||
surface = Color.Black,
|
||||
surfaceVariant = SystemGrey5Dark,
|
||||
onSurface = Color.White,
|
||||
onSurfaceVariant = Color.White,
|
||||
)
|
||||
/**
|
||||
* Inspired from https://medium.com/@lucasyujideveloper/54cbcbde1ace
|
||||
*/
|
||||
object ElementTheme {
|
||||
val colors: ElementColors
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalColors.current
|
||||
}
|
||||
|
||||
private val LightColorScheme = lightColorScheme(
|
||||
primary = Color.Black,
|
||||
secondary = LightGrey,
|
||||
tertiary = Color.Black,
|
||||
background = Color.White,
|
||||
onBackground = Color.Black,
|
||||
surface = Color.White,
|
||||
surfaceVariant = SystemGrey5Light,
|
||||
onSurface = Color.Black,
|
||||
onSurfaceVariant = Color.Black,
|
||||
|
||||
/* Other default colors to override
|
||||
background = Color(0xFFFFFBFE),
|
||||
surface = Color(0xFFFFFBFE),
|
||||
onPrimary = Color.White,
|
||||
onSecondary = Color.White,
|
||||
onTertiary = Color.White,
|
||||
onBackground = Color(0xFF1C1B1F),
|
||||
onSurface = Color(0xFF1C1B1F),
|
||||
*/
|
||||
)
|
||||
@Suppress("CompositionLocalAllowlist")
|
||||
val LocalIsDarkTheme = compositionLocalOf<Boolean> { error("Not defined") }
|
||||
/* Global variables (application level) */
|
||||
val LocalColors = staticCompositionLocalOf { elementColorsLight() }
|
||||
|
||||
@Composable
|
||||
fun ElementXTheme(
|
||||
fun ElementTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
// Dynamic color is available on Android 12+
|
||||
dynamicColor: Boolean = false,
|
||||
content: @Composable () -> Unit
|
||||
dynamicColor: Boolean = false, /* true to enable MaterialYou */
|
||||
lightColors: ElementColors = elementColorsLight(),
|
||||
darkColors: ElementColors = elementColorsDark(),
|
||||
materialLightColors: ColorScheme = materialColorSchemeLight,
|
||||
materialDarkColors: ColorScheme = materialColorSchemeDark,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val useDarkIcons = !darkTheme
|
||||
val currentColor = remember { if (darkTheme) darkColors else lightColors }
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val context = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
}
|
||||
darkTheme -> DarkColorScheme
|
||||
else -> LightColorScheme
|
||||
darkTheme -> materialDarkColors
|
||||
else -> materialLightColors
|
||||
}
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val useDarkIcons = !darkTheme
|
||||
|
||||
SideEffect {
|
||||
systemUiController.setStatusBarColor(
|
||||
color = colorScheme.background
|
||||
@@ -94,11 +75,13 @@ fun ElementXTheme(
|
||||
darkIcons = useDarkIcons
|
||||
)
|
||||
}
|
||||
|
||||
CompositionLocalProvider(LocalIsDarkTheme provides darkTheme) {
|
||||
val rememberedColors = remember { currentColor.copy() }.apply { updateColorsFrom(currentColor) }
|
||||
CompositionLocalProvider(
|
||||
LocalColors provides rememberedColors,
|
||||
) {
|
||||
MaterialTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = Typography,
|
||||
// TODO typography =
|
||||
content = content
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.theme
|
||||
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.airbnb.android.showkase.annotation.ShowkaseTypography
|
||||
|
||||
/**
|
||||
* TODO Provide the typo to Material3 theme.
|
||||
*/
|
||||
@ShowkaseTypography(name = "H1", group = "Element")
|
||||
val h1Default: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Body1", group = "Element")
|
||||
val body1Default: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "BodySmall", group = "Element")
|
||||
val bodySmallDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "bodyMedium", group = "Element")
|
||||
val bodyMediumDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.SansSerif,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 18.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Body Large", group = "Element")
|
||||
val bodyLargeDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Headline Small", group = "Element")
|
||||
val headlineSmallDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 24.sp,
|
||||
lineHeight = 30.sp,
|
||||
letterSpacing = 1.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Headline Medium", group = "Element")
|
||||
val headlineMediumDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 28.sp,
|
||||
lineHeight = 34.sp,
|
||||
letterSpacing = 1.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "Headline Large", group = "Element")
|
||||
val headlineLargeDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 32.sp,
|
||||
lineHeight = 38.sp,
|
||||
letterSpacing = 1.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "titleSmall", group = "Element")
|
||||
val titleSmallDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 14.sp,
|
||||
lineHeight = 20.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
@ShowkaseTypography(name = "titleMedium", group = "Element")
|
||||
val titleMediumDefault: TextStyle = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 18.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.5.sp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ButtonElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@Composable
|
||||
fun Button(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
shape: Shape = ButtonDefaults.shape,
|
||||
colors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
elevation: ButtonElevation? = ButtonDefaults.buttonElevation(),
|
||||
border: BorderStroke? = null,
|
||||
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
androidx.compose.material3.Button(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
elevation = elevation,
|
||||
border = border,
|
||||
contentPadding = contentPadding,
|
||||
interactionSource = interactionSource,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ButtonsLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ButtonsDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
Button(onClick = {}, enabled = true) {
|
||||
Text(text = "Click me! - Enabled")
|
||||
}
|
||||
Button(onClick = {}, enabled = false) {
|
||||
Text(text = "Click me! - Disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.CheckboxColors
|
||||
import androidx.compose.material3.CheckboxDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@Composable
|
||||
fun Checkbox(
|
||||
checked: Boolean,
|
||||
onCheckedChange: ((Boolean) -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
colors: CheckboxColors = CheckboxDefaults.colors(),
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
androidx.compose.material3.Checkbox(
|
||||
checked = checked,
|
||||
onCheckedChange = onCheckedChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
colors = colors,
|
||||
interactionSource = interactionSource,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CheckboxesLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CheckboxesDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
Checkbox(onCheckedChange = {}, enabled = true, checked = true)
|
||||
Checkbox(onCheckedChange = {}, enabled = true, checked = false)
|
||||
Checkbox(onCheckedChange = {}, enabled = false, checked = true)
|
||||
Checkbox(onCheckedChange = {}, enabled = false, checked = false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
@Composable
|
||||
fun CircularProgressIndicator(
|
||||
progress: Float,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = ProgressIndicatorDefaults.circularColor,
|
||||
strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth
|
||||
) {
|
||||
androidx.compose.material3.CircularProgressIndicator(
|
||||
modifier = modifier,
|
||||
progress = progress,
|
||||
color = color,
|
||||
strokeWidth = strokeWidth,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CircularProgressIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = ProgressIndicatorDefaults.circularColor,
|
||||
strokeWidth: Dp = ProgressIndicatorDefaults.CircularStrokeWidth,
|
||||
) {
|
||||
androidx.compose.material3.CircularProgressIndicator(
|
||||
modifier = modifier,
|
||||
color = color,
|
||||
strokeWidth = strokeWidth,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.material3.DividerDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@Composable
|
||||
fun Divider(
|
||||
modifier: Modifier = Modifier,
|
||||
thickness: Dp = DividerDefaults.Thickness,
|
||||
color: Color = DividerDefaults.color,
|
||||
) {
|
||||
androidx.compose.material3.Divider(
|
||||
modifier = modifier,
|
||||
thickness = thickness,
|
||||
color = color,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun DividerLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun DividerDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Divider()
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.material3.FloatingActionButtonDefaults
|
||||
import androidx.compose.material3.FloatingActionButtonElevation
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
|
||||
@Composable
|
||||
fun FloatingActionButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = FloatingActionButtonDefaults.shape,
|
||||
containerColor: Color = FloatingActionButtonDefaults.containerColor,
|
||||
contentColor: Color = contentColorFor(containerColor),
|
||||
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
androidx.compose.material3.FloatingActionButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
elevation = elevation,
|
||||
interactionSource = interactionSource,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
@Composable
|
||||
fun Icon(
|
||||
imageVector: ImageVector,
|
||||
contentDescription: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = LocalContentColor.current
|
||||
) {
|
||||
androidx.compose.material3.Icon(
|
||||
imageVector = imageVector,
|
||||
contentDescription = contentDescription,
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Icon(
|
||||
bitmap: ImageBitmap,
|
||||
contentDescription: String?,
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = LocalContentColor.current
|
||||
) {
|
||||
androidx.compose.material3.Icon(
|
||||
bitmap = bitmap,
|
||||
contentDescription = contentDescription,
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.material3.IconButtonDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@Composable
|
||||
fun IconButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
androidx.compose.material3.IconButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
colors = IconButtonDefaults.iconButtonColors(),
|
||||
interactionSource = interactionSource,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.TopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MediumTopAppBar(
|
||||
title: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
|
||||
colors: TopAppBarColors = TopAppBarDefaults.mediumTopAppBarColors(),
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||
) {
|
||||
androidx.compose.material3.MediumTopAppBar(
|
||||
title = title,
|
||||
modifier = modifier,
|
||||
navigationIcon = navigationIcon,
|
||||
actions = actions,
|
||||
windowInsets = windowInsets,
|
||||
colors = colors,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.ModalBottomSheetDefaults
|
||||
import androidx.compose.material.ModalBottomSheetState
|
||||
import androidx.compose.material.ModalBottomSheetValue
|
||||
import androidx.compose.material.contentColorFor
|
||||
import androidx.compose.material.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.Dp
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun ModalBottomSheetLayout(
|
||||
sheetContent: @Composable ColumnScope.() -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
sheetState: ModalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden),
|
||||
sheetShape: Shape = MaterialTheme.shapes.large,
|
||||
sheetElevation: Dp = ModalBottomSheetDefaults.Elevation,
|
||||
sheetBackgroundColor: Color = MaterialTheme.colors.surface,
|
||||
sheetContentColor: Color = contentColorFor(sheetBackgroundColor),
|
||||
scrimColor: Color = ModalBottomSheetDefaults.scrimColor,
|
||||
content: @Composable () -> Unit = {}
|
||||
) {
|
||||
androidx.compose.material.ModalBottomSheetLayout(
|
||||
sheetContent = sheetContent,
|
||||
modifier = modifier,
|
||||
sheetState = sheetState,
|
||||
sheetShape = sheetShape,
|
||||
sheetElevation = sheetElevation,
|
||||
sheetBackgroundColor = sheetBackgroundColor,
|
||||
sheetContentColor = sheetContentColor,
|
||||
scrimColor = scrimColor,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun OutlinedTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
supportingText: @Composable (() -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = TextFieldDefaults.outlinedShape,
|
||||
colors: TextFieldColors = TextFieldDefaults.outlinedTextFieldColors()
|
||||
) {
|
||||
androidx.compose.material3.OutlinedTextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = textStyle,
|
||||
label = label,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText,
|
||||
isError = isError,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun OutlinedTextFieldsLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun OutlinedTextFieldsDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = false, enabled = true, readOnly = true)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = false, enabled = true, readOnly = false)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = false, enabled = false, readOnly = true)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = false, enabled = false, readOnly = false)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = true, enabled = true, readOnly = true)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = true, enabled = true, readOnly = false)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = true, enabled = false, readOnly = true)
|
||||
OutlinedTextField(onValueChange = {}, value = "Content", isError = true, enabled = false, readOnly = false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FabPosition
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ScaffoldDefaults
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun Scaffold(
|
||||
modifier: Modifier = Modifier,
|
||||
topBar: @Composable () -> Unit = {},
|
||||
bottomBar: @Composable () -> Unit = {},
|
||||
snackbarHost: @Composable () -> Unit = {},
|
||||
floatingActionButton: @Composable () -> Unit = {},
|
||||
floatingActionButtonPosition: FabPosition = FabPosition.End,
|
||||
containerColor: Color = MaterialTheme.colorScheme.background,
|
||||
contentColor: Color = contentColorFor(containerColor),
|
||||
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
) {
|
||||
androidx.compose.material3.Scaffold(
|
||||
modifier = modifier,
|
||||
topBar = topBar,
|
||||
bottomBar = bottomBar,
|
||||
snackbarHost = snackbarHost,
|
||||
floatingActionButton = floatingActionButton,
|
||||
floatingActionButtonPosition = floatingActionButtonPosition,
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
contentWindowInsets = contentWindowInsets,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material3.SliderColors
|
||||
import androidx.compose.material3.SliderDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@Composable
|
||||
fun Slider(
|
||||
value: Float,
|
||||
onValueChange: (Float) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
|
||||
/*@IntRange(from = 0)*/
|
||||
steps: Int = 0,
|
||||
onValueChangeFinished: (() -> Unit)? = null,
|
||||
colors: SliderColors = SliderDefaults.colors(),
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
androidx.compose.material3.Slider(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
valueRange = valueRange,
|
||||
steps = steps,
|
||||
onValueChangeFinished = onValueChangeFinished,
|
||||
colors = colors,
|
||||
interactionSource = interactionSource,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SlidersLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SlidersDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
Slider(onValueChange = {}, value = 0.33f, enabled = true)
|
||||
Slider(onValueChange = {}, value = 0.33f, enabled = false)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.RectangleShape
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun Surface(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = RectangleShape,
|
||||
color: Color = MaterialTheme.colorScheme.surface,
|
||||
contentColor: Color = contentColorFor(color),
|
||||
tonalElevation: Dp = 0.dp,
|
||||
shadowElevation: Dp = 0.dp,
|
||||
border: BorderStroke? = null,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
androidx.compose.material3.Surface(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
color = color,
|
||||
contentColor = contentColor,
|
||||
tonalElevation = tonalElevation,
|
||||
shadowElevation = shadowElevation,
|
||||
border = border,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
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.width
|
||||
import androidx.compose.foundation.text.InlineTextContent
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.contentColorFor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.TextLayoutResult
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.TextUnit
|
||||
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.utils.toHrf
|
||||
import kotlinx.collections.immutable.ImmutableMap
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
|
||||
@Composable
|
||||
fun Text(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color.Unspecified,
|
||||
fontSize: TextUnit = TextUnit.Unspecified,
|
||||
fontStyle: FontStyle? = null,
|
||||
fontWeight: FontWeight? = null,
|
||||
fontFamily: FontFamily? = null,
|
||||
letterSpacing: TextUnit = TextUnit.Unspecified,
|
||||
textDecoration: TextDecoration? = null,
|
||||
textAlign: TextAlign? = null,
|
||||
lineHeight: TextUnit = TextUnit.Unspecified,
|
||||
overflow: TextOverflow = TextOverflow.Clip,
|
||||
softWrap: Boolean = true,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||
style: TextStyle = LocalTextStyle.current
|
||||
) {
|
||||
androidx.compose.material3.Text(
|
||||
text = text,
|
||||
modifier = modifier,
|
||||
color = color,
|
||||
fontSize = fontSize,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = fontWeight,
|
||||
fontFamily = fontFamily,
|
||||
letterSpacing = letterSpacing,
|
||||
textDecoration = textDecoration,
|
||||
textAlign = textAlign,
|
||||
lineHeight = lineHeight,
|
||||
overflow = overflow,
|
||||
softWrap = softWrap,
|
||||
maxLines = maxLines,
|
||||
onTextLayout = onTextLayout,
|
||||
style = style,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Text(
|
||||
text: AnnotatedString,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color.Unspecified,
|
||||
fontSize: TextUnit = TextUnit.Unspecified,
|
||||
fontStyle: FontStyle? = null,
|
||||
fontWeight: FontWeight? = null,
|
||||
fontFamily: FontFamily? = null,
|
||||
letterSpacing: TextUnit = TextUnit.Unspecified,
|
||||
textDecoration: TextDecoration? = null,
|
||||
textAlign: TextAlign? = null,
|
||||
lineHeight: TextUnit = TextUnit.Unspecified,
|
||||
overflow: TextOverflow = TextOverflow.Clip,
|
||||
softWrap: Boolean = true,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
inlineContent: ImmutableMap<String, InlineTextContent> = persistentMapOf(),
|
||||
onTextLayout: (TextLayoutResult) -> Unit = {},
|
||||
style: TextStyle = LocalTextStyle.current
|
||||
) {
|
||||
androidx.compose.material3.Text(
|
||||
text = text,
|
||||
modifier = modifier,
|
||||
color = color,
|
||||
fontSize = fontSize,
|
||||
fontStyle = fontStyle,
|
||||
fontWeight = fontWeight,
|
||||
fontFamily = fontFamily,
|
||||
letterSpacing = letterSpacing,
|
||||
textDecoration = textDecoration,
|
||||
textAlign = textAlign,
|
||||
lineHeight = lineHeight,
|
||||
overflow = overflow,
|
||||
softWrap = softWrap,
|
||||
maxLines = maxLines,
|
||||
inlineContent = inlineContent,
|
||||
onTextLayout = onTextLayout,
|
||||
style = style,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TextLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TextDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
val colors = mapOf(
|
||||
"primary" to MaterialTheme.colorScheme.primary,
|
||||
"secondary" to MaterialTheme.colorScheme.secondary,
|
||||
"tertiary" to MaterialTheme.colorScheme.tertiary,
|
||||
"background" to MaterialTheme.colorScheme.background,
|
||||
"error" to MaterialTheme.colorScheme.error,
|
||||
"surface" to MaterialTheme.colorScheme.surface,
|
||||
"surfaceVariant" to MaterialTheme.colorScheme.surfaceVariant,
|
||||
"primaryContainer" to MaterialTheme.colorScheme.primaryContainer,
|
||||
"secondaryContainer" to MaterialTheme.colorScheme.secondaryContainer,
|
||||
"tertiaryContainer" to MaterialTheme.colorScheme.tertiaryContainer,
|
||||
// "inversePrimary" to MaterialTheme.colorScheme.inversePrimary,
|
||||
"errorContainer" to MaterialTheme.colorScheme.errorContainer,
|
||||
"inverseSurface" to MaterialTheme.colorScheme.inverseSurface,
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.width(IntrinsicSize.Max)
|
||||
) {
|
||||
colors.keys.forEach { name ->
|
||||
val color = colors[name]!!
|
||||
val textColor = contentColorFor(backgroundColor = color)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.background(color = color)
|
||||
.fillMaxWidth()
|
||||
.padding(2.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Text on $name\n${textColor.toHrf()} on ${color.toHrf()}",
|
||||
color = textColor,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.TextFieldColors
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
readOnly: Boolean = false,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
supportingText: @Composable (() -> Unit)? = null,
|
||||
isError: Boolean = false,
|
||||
visualTransformation: VisualTransformation = VisualTransformation.None,
|
||||
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
||||
keyboardActions: KeyboardActions = KeyboardActions.Default,
|
||||
singleLine: Boolean = false,
|
||||
maxLines: Int = Int.MAX_VALUE,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
shape: Shape = TextFieldDefaults.filledShape,
|
||||
colors: TextFieldColors = TextFieldDefaults.textFieldColors()
|
||||
) {
|
||||
androidx.compose.material3.TextField(
|
||||
value = value,
|
||||
onValueChange = onValueChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
readOnly = readOnly,
|
||||
textStyle = textStyle,
|
||||
label = label,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
supportingText = supportingText,
|
||||
isError = isError,
|
||||
visualTransformation = visualTransformation,
|
||||
keyboardOptions = keyboardOptions,
|
||||
keyboardActions = keyboardActions,
|
||||
singleLine = singleLine,
|
||||
maxLines = maxLines,
|
||||
interactionSource = interactionSource,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.TopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TopAppBar(
|
||||
title: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
|
||||
colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors(),
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null
|
||||
) {
|
||||
androidx.compose.material3.TopAppBar(
|
||||
title = title,
|
||||
modifier = modifier,
|
||||
navigationIcon = navigationIcon,
|
||||
actions = actions,
|
||||
windowInsets = windowInsets,
|
||||
colors = colors,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.theme.previews
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
internal fun ColorListPreview(
|
||||
backgroundColor: Color,
|
||||
foregroundColor: Color,
|
||||
colors: Map<String, Color>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
.background(color = backgroundColor)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
colors.keys.forEach { name ->
|
||||
val color = colors[name]!!
|
||||
ColorPreview(backgroundColor = backgroundColor, foregroundColor = foregroundColor, name = name, color = color)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.theme.previews
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.toHrf
|
||||
|
||||
@Composable
|
||||
internal fun ColorPreview(
|
||||
backgroundColor: Color,
|
||||
foregroundColor: Color,
|
||||
name: String, color: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier.fillMaxWidth()) {
|
||||
Text(text = name + " " + color.toHrf(), fontSize = 6.sp, color = foregroundColor)
|
||||
val backgroundBrush = Brush.linearGradient(
|
||||
listOf(
|
||||
backgroundColor,
|
||||
foregroundColor,
|
||||
)
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.background(backgroundBrush)
|
||||
) {
|
||||
repeat(2) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(1.dp)
|
||||
.background(color = color)
|
||||
.height(10.dp)
|
||||
.weight(1f)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.theme.previews
|
||||
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@Composable
|
||||
internal fun ColorsSchemePreview(
|
||||
backgroundColor: Color,
|
||||
foregroundColor: Color,
|
||||
colorScheme: ColorScheme,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val colors = mapOf(
|
||||
"primary" to colorScheme.primary,
|
||||
"onPrimary" to colorScheme.onPrimary,
|
||||
"primaryContainer" to colorScheme.primaryContainer,
|
||||
"onPrimaryContainer" to colorScheme.onPrimaryContainer,
|
||||
"inversePrimary" to colorScheme.inversePrimary,
|
||||
"secondary" to colorScheme.secondary,
|
||||
"onSecondary" to colorScheme.onSecondary,
|
||||
"secondaryContainer" to colorScheme.secondaryContainer,
|
||||
"onSecondaryContainer" to colorScheme.onSecondaryContainer,
|
||||
"tertiary" to colorScheme.tertiary,
|
||||
"onTertiary" to colorScheme.onTertiary,
|
||||
"tertiaryContainer" to colorScheme.tertiaryContainer,
|
||||
"onTertiaryContainer" to colorScheme.onTertiaryContainer,
|
||||
"background" to colorScheme.background,
|
||||
"onBackground" to colorScheme.onBackground,
|
||||
"surface" to colorScheme.surface,
|
||||
"onSurface" to colorScheme.onSurface,
|
||||
"surfaceVariant" to colorScheme.surfaceVariant,
|
||||
"onSurfaceVariant" to colorScheme.onSurfaceVariant,
|
||||
"surfaceTint" to colorScheme.surfaceTint,
|
||||
"inverseSurface" to colorScheme.inverseSurface,
|
||||
"inverseOnSurface" to colorScheme.inverseOnSurface,
|
||||
"error" to colorScheme.error,
|
||||
"onError" to colorScheme.onError,
|
||||
"errorContainer" to colorScheme.errorContainer,
|
||||
"onErrorContainer" to colorScheme.onErrorContainer,
|
||||
"outline" to colorScheme.outline,
|
||||
"outlineVariant" to colorScheme.outlineVariant,
|
||||
"scrim" to colorScheme.scrim,
|
||||
)
|
||||
ColorListPreview(
|
||||
backgroundColor = backgroundColor,
|
||||
foregroundColor = foregroundColor,
|
||||
colors = colors,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
* 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.
|
||||
@@ -14,20 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.components
|
||||
package io.element.android.libraries.designsystem.utils
|
||||
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
@Composable
|
||||
fun VectorButton(text: String, enabled: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
Button(
|
||||
onClick = onClick,
|
||||
enabled = enabled,
|
||||
modifier = modifier
|
||||
) {
|
||||
Text(text = text)
|
||||
}
|
||||
/**
|
||||
* Convert color to Human Readable Format.
|
||||
*/
|
||||
internal fun Color.toHrf(): String {
|
||||
return "0x" + value.toString(16).take(8).uppercase()
|
||||
}
|
||||
@@ -23,5 +23,5 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.google.android.material:material:1.7.0")
|
||||
implementation(libs.androidx.material)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.matrix.sync.roomListDiff
|
||||
import io.element.android.libraries.matrix.sync.state
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.cancelChildren
|
||||
@@ -29,7 +28,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.sample
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntry
|
||||
|
||||
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -36,6 +35,9 @@ import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
@@ -64,8 +66,9 @@ fun MatrixUserHeader(
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
text = matrixUser.getBestName(),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
// Id
|
||||
if (matrixUser.username.isNullOrEmpty().not()) {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
@@ -82,7 +85,14 @@ fun MatrixUserHeader(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserHeaderPreview() {
|
||||
fun MatrixUserHeaderLightPreview() = ElementPreviewLight { ContentToPreview1() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserHeaderDarkPreview() = ElementPreviewDark { ContentToPreview1() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview1() {
|
||||
MatrixUserHeader(
|
||||
MatrixUser(
|
||||
id = UserId("@alice:server.org"),
|
||||
@@ -94,7 +104,14 @@ fun MatrixUserHeaderPreview() {
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserHeaderNoUsernamePreview() {
|
||||
fun MatrixUserHeaderNoUserNameLightPreview() = ElementPreviewLight { ContentToPreview2() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserHeaderNoUserNameDarkPreview() = ElementPreviewDark { ContentToPreview2() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview2() {
|
||||
MatrixUserHeader(
|
||||
MatrixUser(
|
||||
id = UserId("@alice:server.org"),
|
||||
|
||||
@@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -35,6 +34,9 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.matrix.core.UserId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import io.element.android.libraries.matrix.ui.model.getBestName
|
||||
@@ -68,7 +70,8 @@ fun MatrixUserRow(
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
text = matrixUser.getBestName(),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
// Id
|
||||
if (matrixUser.username.isNullOrEmpty().not()) {
|
||||
@@ -86,7 +89,14 @@ fun MatrixUserRow(
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserRowPreview() {
|
||||
fun MatrixUserRowLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun MatrixUserRowDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
MatrixUserRow(
|
||||
MatrixUser(
|
||||
id = UserId("@alice:server.org"),
|
||||
|
||||
@@ -35,8 +35,9 @@ dependencies {
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.matrix)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(libs.wysiwyg)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation("com.google.android.material:material:1.7.0")
|
||||
implementation(libs.androidx.material)
|
||||
ksp(libs.showkase.processor)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import android.net.Uri
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -33,6 +33,9 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
@@ -123,7 +126,8 @@ private fun FakeComposer(
|
||||
.align(Alignment.Center),
|
||||
textAlign = TextAlign.Center,
|
||||
text = "Composer Preview",
|
||||
fontSize = 20.sp
|
||||
fontSize = 20.sp,
|
||||
color = MaterialTheme.colorScheme.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -145,7 +149,14 @@ private fun MessageComposerView.setup(isDarkMode: Boolean, composerMode: Message
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TextComposerPreview() {
|
||||
fun TextComposerLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TextComposerDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
TextComposer(
|
||||
onSendMessage = {},
|
||||
fullscreen = false,
|
||||
|
||||
@@ -20,10 +20,6 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -32,6 +28,12 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
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.Button
|
||||
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.Text
|
||||
|
||||
@Composable
|
||||
fun ShowkaseButton(
|
||||
@@ -59,8 +61,15 @@ fun ShowkaseButton(
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(group = "Buttons", name = "Showkase button")
|
||||
@Preview
|
||||
@Composable
|
||||
fun ShowkaseButtonPreview() {
|
||||
fun ShowkaseButtonLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ShowkaseButtonDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
ShowkaseButton()
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import app.cash.paparazzi.Paparazzi
|
||||
import com.airbnb.android.showkase.models.Showkase
|
||||
import com.google.testing.junit.testparameterinjector.TestParameter
|
||||
import com.google.testing.junit.testparameterinjector.TestParameterInjector
|
||||
import io.element.android.libraries.designsystem.ElementXTheme
|
||||
import io.element.android.libraries.designsystem.theme.ElementTheme
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -75,7 +75,6 @@ class ScreenshotTest {
|
||||
@TestParameter(valuesProvider = PreviewProvider::class) componentTestPreview: TestPreview,
|
||||
@TestParameter baseDeviceConfig: BaseDeviceConfig,
|
||||
@TestParameter(value = ["1.0"/*, "1.5"*/]) fontScale: Float,
|
||||
@TestParameter(value = ["light", "dark"]) theme: String,
|
||||
@TestParameter(value = ["en" /*"fr", "de", "ru"*/]) localeStr: String,
|
||||
) {
|
||||
paparazzi.unsafeUpdateConfig(
|
||||
@@ -101,7 +100,7 @@ class ScreenshotTest {
|
||||
override fun getOnBackPressedDispatcher() = OnBackPressedDispatcher()
|
||||
}
|
||||
) {
|
||||
ElementXTheme(darkTheme = (theme == "dark")) {
|
||||
ElementTheme {
|
||||
Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
|
||||
componentTestPreview.Content()
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user