fix: bottom sheet IME padding (#437)

closes #436
This commit is contained in:
Diego Beraldin 2024-01-10 09:00:47 +01:00 committed by GitHub
parent f75057335f
commit ac9a55c964
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 461 additions and 473 deletions

View File

@ -85,100 +85,96 @@ class BanUserScreen(
}.launchIn(this)
}
Box(
Column(
modifier = Modifier.imePadding(),
contentAlignment = Alignment.BottomCenter,
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
) {
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally
) {
BottomSheetHandle()
val title = if (newValue) {
stringResource(MR.strings.mod_action_ban)
} else {
stringResource(MR.strings.mod_action_allow)
}
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
BottomSheetHandle()
val title = if (newValue) {
stringResource(MR.strings.mod_action_ban)
} else {
stringResource(MR.strings.mod_action_allow)
}
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
onClick = {
model.reduce(BanUserMviModel.Intent.Submit)
},
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(BanUserMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
onClick = {
model.reduce(BanUserMviModel.Intent.Submit)
},
)
Spacer(Modifier.height(Spacing.xxl))
}
if (uiState.loading) {
ProgressHud()
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(BanUserMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
Spacer(Modifier.height(Spacing.xxl))
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
if (uiState.loading) {
ProgressHud()
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
}
}

View File

@ -79,99 +79,95 @@ class CreateReportScreen(
}.launchIn(this)
}
Box(
Column(
modifier = Modifier.imePadding(),
contentAlignment = Alignment.BottomCenter,
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
) {
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
BottomSheetHandle()
val title = when {
commentId != null -> stringResource(MR.strings.create_report_title_comment)
else -> stringResource(MR.strings.create_report_title_post)
}
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
BottomSheetHandle()
val title = when {
commentId != null -> stringResource(MR.strings.create_report_title_comment)
else -> stringResource(MR.strings.create_report_title_post)
}
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
onClick = {
model.reduce(CreateReportMviModel.Intent.Send)
},
Text(
text = title,
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(CreateReportMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
onClick = {
model.reduce(CreateReportMviModel.Intent.Send)
},
)
Spacer(Modifier.height(Spacing.xxl))
}
if (uiState.loading) {
ProgressHud()
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(CreateReportMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
Spacer(Modifier.height(Spacing.xxl))
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
if (uiState.loading) {
ProgressHud()
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
}
}

View File

@ -11,8 +11,10 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.HelpOutline
@ -98,254 +100,252 @@ class LoginBottomSheet : Screen {
val uriHandler = LocalUriHandler.current
val settingsRepository = remember { getSettingsRepository() }
Box(
modifier = Modifier.imePadding(),
contentAlignment = Alignment.BottomCenter,
) {
Column(
modifier = Modifier.padding(
Column(
modifier = Modifier
.imePadding()
.verticalScroll(rememberScrollState())
.padding(
top = Spacing.s,
start = Spacing.s,
end = Spacing.s,
bottom = Spacing.m,
),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
BottomSheetHandle()
Text(
modifier = Modifier.padding(start = Spacing.s, top = Spacing.s),
text = stringResource(MR.strings.profile_button_login),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
onClick = rememberCallback {
navigationCoordinator.hideBottomSheet()
navigationCoordinator.handleUrl(
url = HELP_URL,
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
uriHandler = uriHandler,
onOpenWeb = { url ->
navigationCoordinator.pushScreen(WebViewScreen(url))
}
)
},
) {
Icon(
imageVector = Icons.Default.HelpOutline,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
}
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Box {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
BottomSheetHandle()
Text(
modifier = Modifier.padding(start = Spacing.s, top = Spacing.s),
text = stringResource(MR.strings.profile_button_login),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
val instanceFocusRequester = remember { FocusRequester() }
val usernameFocusRequester = remember { FocusRequester() }
val passwordFocusRequester = remember { FocusRequester() }
val tokenFocusRequester = remember { FocusRequester() }
// instance name
TextField(
modifier = Modifier.focusRequester(instanceFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_instance_name))
},
singleLine = true,
value = uiState.instanceName,
isError = uiState.instanceNameError != null,
keyboardActions = KeyboardActions(
onNext = {
usernameFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
autoCorrect = false,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetInstanceName(value))
},
supportingText = {
if (uiState.instanceNameError != null) {
Text(
text = uiState.instanceNameError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
trailingIcon = {
if (uiState.instanceName.isNotEmpty()) {
Icon(
modifier = Modifier.onClick(
onClick = rememberCallback(model) {
model.reduce(
LoginMviModel.Intent.SetInstanceName("")
)
},
),
imageVector = Icons.Default.Clear,
contentDescription = null,
)
}
},
)
// user name
TextField(
modifier = Modifier.focusRequester(usernameFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_user_name))
},
singleLine = true,
value = uiState.username,
isError = uiState.usernameError != null,
keyboardActions = KeyboardActions(
onNext = {
passwordFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
autoCorrect = false,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetUsername(value))
},
supportingText = {
if (uiState.usernameError != null) {
Text(
text = uiState.usernameError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
// password
var transformation: VisualTransformation by remember {
mutableStateOf(PasswordVisualTransformation())
}
TextField(
modifier = Modifier.focusRequester(passwordFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_password))
},
singleLine = true,
value = uiState.password,
isError = uiState.passwordError != null,
keyboardActions = KeyboardActions(
onNext = {
tokenFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetPassword(value))
},
visualTransformation = transformation,
trailingIcon = {
Image(
modifier = Modifier.onClick(
onClick = rememberCallback {
transformation =
if (transformation == VisualTransformation.None) {
PasswordVisualTransformation()
} else {
VisualTransformation.None
}
},
),
imageVector = if (transformation == VisualTransformation.None) {
Icons.Default.VisibilityOff
} else {
Icons.Default.Visibility
},
contentDescription = null,
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onBackground),
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
onClick = rememberCallback {
navigationCoordinator.hideBottomSheet()
navigationCoordinator.handleUrl(
url = HELP_URL,
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
uriHandler = uriHandler,
onOpenWeb = { url ->
navigationCoordinator.pushScreen(WebViewScreen(url))
}
)
},
supportingText = {
if (uiState.passwordError != null) {
Text(
text = uiState.passwordError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
// TOTP 2FA token
TextField(
modifier = Modifier.focusRequester(tokenFocusRequester),
label = {
Row(
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
verticalAlignment = Alignment.Bottom,
) {
Text(text = stringResource(MR.strings.login_field_token))
Text(
text = stringResource(MR.strings.login_field_label_optional),
style = MaterialTheme.typography.labelSmall,
)
}
},
singleLine = true,
value = uiState.totp2faToken,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetTotp2faToken(value))
},
visualTransformation = PasswordVisualTransformation(),
)
Spacer(modifier = Modifier.height(Spacing.m))
Button(
modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = rememberCallback(model) {
model.reduce(LoginMviModel.Intent.Confirm)
},
) {
Row(
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
verticalAlignment = Alignment.CenterVertically,
) {
if (uiState.loading) {
CircularProgressIndicator(
modifier = Modifier.size(IconSize.s),
color = MaterialTheme.colorScheme.onPrimary,
)
}
Text(stringResource(MR.strings.button_confirm))
}
Icon(
imageVector = Icons.Default.HelpOutline,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
}
Spacer(modifier = Modifier.height(Spacing.m))
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
val instanceFocusRequester = remember { FocusRequester() }
val usernameFocusRequester = remember { FocusRequester() }
val passwordFocusRequester = remember { FocusRequester() }
val tokenFocusRequester = remember { FocusRequester() }
// instance name
TextField(
modifier = Modifier.focusRequester(instanceFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_instance_name))
},
singleLine = true,
value = uiState.instanceName,
isError = uiState.instanceNameError != null,
keyboardActions = KeyboardActions(
onNext = {
usernameFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
autoCorrect = false,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetInstanceName(value))
},
supportingText = {
if (uiState.instanceNameError != null) {
Text(
text = uiState.instanceNameError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
trailingIcon = {
if (uiState.instanceName.isNotEmpty()) {
Icon(
modifier = Modifier.onClick(
onClick = rememberCallback(model) {
model.reduce(
LoginMviModel.Intent.SetInstanceName("")
)
},
),
imageVector = Icons.Default.Clear,
contentDescription = null,
)
}
},
)
// user name
TextField(
modifier = Modifier.focusRequester(usernameFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_user_name))
},
singleLine = true,
value = uiState.username,
isError = uiState.usernameError != null,
keyboardActions = KeyboardActions(
onNext = {
passwordFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Email,
autoCorrect = false,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetUsername(value))
},
supportingText = {
if (uiState.usernameError != null) {
Text(
text = uiState.usernameError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
// password
var transformation: VisualTransformation by remember {
mutableStateOf(PasswordVisualTransformation())
}
TextField(
modifier = Modifier.focusRequester(passwordFocusRequester),
label = {
Text(text = stringResource(MR.strings.login_field_password))
},
singleLine = true,
value = uiState.password,
isError = uiState.passwordError != null,
keyboardActions = KeyboardActions(
onNext = {
tokenFocusRequester.requestFocus()
},
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Next,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetPassword(value))
},
visualTransformation = transformation,
trailingIcon = {
Image(
modifier = Modifier.onClick(
onClick = rememberCallback {
transformation =
if (transformation == VisualTransformation.None) {
PasswordVisualTransformation()
} else {
VisualTransformation.None
}
},
),
imageVector = if (transformation == VisualTransformation.None) {
Icons.Default.VisibilityOff
} else {
Icons.Default.Visibility
},
contentDescription = null,
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onBackground),
)
},
supportingText = {
if (uiState.passwordError != null) {
Text(
text = uiState.passwordError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
// TOTP 2FA token
TextField(
modifier = Modifier.focusRequester(tokenFocusRequester),
label = {
Row(
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
verticalAlignment = Alignment.Bottom,
) {
Text(text = stringResource(MR.strings.login_field_token))
Text(
text = stringResource(MR.strings.login_field_label_optional),
style = MaterialTheme.typography.labelSmall,
)
}
},
singleLine = true,
value = uiState.totp2faToken,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
onValueChange = rememberCallbackArgs(model) { value ->
model.reduce(LoginMviModel.Intent.SetTotp2faToken(value))
},
visualTransformation = PasswordVisualTransformation(),
)
Spacer(modifier = Modifier.height(Spacing.m))
Button(
modifier = Modifier.align(Alignment.CenterHorizontally),
onClick = rememberCallback(model) {
model.reduce(LoginMviModel.Intent.Confirm)
},
) {
Row(
horizontalArrangement = Arrangement.spacedBy(Spacing.s),
verticalAlignment = Alignment.CenterVertically,
) {
if (uiState.loading) {
CircularProgressIndicator(
modifier = Modifier.size(IconSize.s),
color = MaterialTheme.colorScheme.onPrimary,
)
}
Text(stringResource(MR.strings.button_confirm))
}
}
Spacer(modifier = Modifier.height(Spacing.m))
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
}
}

View File

@ -79,95 +79,91 @@ class RemoveScreen(
}.launchIn(this)
}
Box(
Column(
modifier = Modifier.imePadding(),
contentAlignment = Alignment.BottomCenter,
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Column(
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally,
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
) {
Box(
modifier = Modifier.fillMaxWidth().padding(top = Spacing.s),
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier.align(Alignment.TopCenter),
verticalArrangement = Arrangement.spacedBy(Spacing.s),
horizontalAlignment = Alignment.CenterHorizontally
) {
BottomSheetHandle()
Text(
text = stringResource(MR.strings.mod_action_remove),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
onClick = {
model.reduce(RemoveMviModel.Intent.Submit)
},
BottomSheetHandle()
Text(
text = stringResource(MR.strings.mod_action_remove),
style = MaterialTheme.typography.titleLarge,
color = MaterialTheme.colorScheme.onBackground,
)
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
IconButton(
modifier = Modifier.align(Alignment.TopEnd),
content = {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null,
tint = MaterialTheme.colorScheme.onBackground,
)
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(RemoveMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
onClick = {
model.reduce(RemoveMviModel.Intent.Submit)
},
)
Spacer(Modifier.height(Spacing.xxl))
}
if (uiState.loading) {
ProgressHud()
}
val commentFocusRequester = remember { FocusRequester() }
TextField(
modifier = Modifier
.focusRequester(commentFocusRequester)
.heightIn(min = 300.dp, max = 500.dp)
.fillMaxWidth(),
colors = TextFieldDefaults.colors(
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
),
label = {
Text(text = stringResource(MR.strings.create_report_placeholder))
},
textStyle = MaterialTheme.typography.bodyMedium,
value = uiState.text,
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
autoCorrect = true,
),
onValueChange = { value ->
model.reduce(RemoveMviModel.Intent.SetText(value))
},
isError = uiState.textError != null,
supportingText = {
if (uiState.textError != null) {
Text(
text = uiState.textError?.localized().orEmpty(),
color = MaterialTheme.colorScheme.error,
)
}
},
)
Spacer(Modifier.height(Spacing.xxl))
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
if (uiState.loading) {
ProgressHud()
}
SnackbarHost(
modifier = Modifier.padding(bottom = Spacing.xxxl),
hostState = snackbarHostState
) { data ->
Snackbar(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
snackbarData = data,
)
}
}
}