[Strings] Use strings from localazy.
This commit is contained in:
parent
d449ede86d
commit
c774f7529e
33 changed files with 216 additions and 182 deletions
|
|
@ -29,6 +29,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import io.element.android.features.createroom.impl.R
|
||||||
import io.element.android.features.selectusers.api.SelectUsersView
|
import io.element.android.features.selectusers.api.SelectUsersView
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
|
|
@ -85,7 +86,7 @@ fun AddPeopleViewTopBar(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.add_people),
|
text = stringResource(id = R.string.screen_create_room_add_people_title),
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import io.element.android.features.createroom.impl.R
|
||||||
import io.element.android.features.selectusers.api.SelectUsersView
|
import io.element.android.features.selectusers.api.SelectUsersView
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
|
@ -94,7 +95,7 @@ fun CreateRoomRootViewTopBar(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.start_chat),
|
text = stringResource(id = StringR.string.action_start_chat),
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
)
|
||||||
|
|
@ -116,12 +117,12 @@ fun CreateRoomActionButtonsList(
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
CreateRoomActionButton(
|
CreateRoomActionButton(
|
||||||
iconRes = DrawableR.drawable.ic_groups,
|
iconRes = DrawableR.drawable.ic_groups,
|
||||||
text = stringResource(id = StringR.string.new_room),
|
text = stringResource(id = R.string.screen_create_room_action_create_room),
|
||||||
onClick = onNewRoomClicked,
|
onClick = onNewRoomClicked,
|
||||||
)
|
)
|
||||||
CreateRoomActionButton(
|
CreateRoomActionButton(
|
||||||
iconRes = DrawableR.drawable.ic_share,
|
iconRes = DrawableR.drawable.ic_share,
|
||||||
text = stringResource(id = StringR.string.invite_people_menu),
|
text = stringResource(id = R.string.screen_create_room_action_invite_people),
|
||||||
onClick = onInvitePeopleClicked,
|
onClick = onInvitePeopleClicked,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ package io.element.android.features.login.impl.changeserver
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import io.element.android.features.login.impl.R
|
||||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||||
import io.element.android.libraries.ui.strings.R
|
|
||||||
|
|
||||||
sealed class ChangeServerError : Throwable() {
|
sealed class ChangeServerError : Throwable() {
|
||||||
data class InlineErrorMessage(@StringRes val messageId: Int) : ChangeServerError() {
|
data class InlineErrorMessage(@StringRes val messageId: Int) : ChangeServerError() {
|
||||||
|
|
@ -32,7 +32,7 @@ sealed class ChangeServerError : Throwable() {
|
||||||
companion object {
|
companion object {
|
||||||
fun from(error: Throwable): ChangeServerError = when (error) {
|
fun from(error: Throwable): ChangeServerError = when (error) {
|
||||||
is AuthenticationException.SlidingSyncNotAvailable -> SlidingSyncAlert
|
is AuthenticationException.SlidingSyncNotAvailable -> SlidingSyncAlert
|
||||||
else -> InlineErrorMessage(R.string.server_selection_invalid_homeserver_error)
|
else -> InlineErrorMessage(R.string.screen_change_server_error_invalid_homeserver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
package io.element.android.features.login.impl.changeserver
|
package io.element.android.features.login.impl.changeserver
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.ui.strings.R
|
import io.element.android.features.login.impl.R
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
|
|
||||||
open class ChangeServerStateProvider : PreviewParameterProvider<ChangeServerState> {
|
open class ChangeServerStateProvider : PreviewParameterProvider<ChangeServerState> {
|
||||||
|
|
@ -28,7 +28,7 @@ open class ChangeServerStateProvider : PreviewParameterProvider<ChangeServerStat
|
||||||
aChangeServerState().copy(homeserver = "matrix.org", changeServerAction = Async.Loading()),
|
aChangeServerState().copy(homeserver = "matrix.org", changeServerAction = Async.Loading()),
|
||||||
aChangeServerState().copy(
|
aChangeServerState().copy(
|
||||||
homeserver = "invalid.org",
|
homeserver = "invalid.org",
|
||||||
changeServerAction = Async.Failure(ChangeServerError.InlineErrorMessage(R.string.server_selection_invalid_homeserver_error))
|
changeServerAction = Async.Failure(ChangeServerError.InlineErrorMessage(R.string.screen_change_server_error_invalid_homeserver))
|
||||||
),
|
),
|
||||||
aChangeServerState().copy(homeserver = "invalid.org", changeServerAction = Async.Failure(ChangeServerError.SlidingSyncAlert)),
|
aChangeServerState().copy(homeserver = "invalid.org", changeServerAction = Async.Failure(ChangeServerError.SlidingSyncAlert)),
|
||||||
aChangeServerState().copy(homeserver = "matrix.org", changeServerAction = Async.Success(Unit)),
|
aChangeServerState().copy(homeserver = "matrix.org", changeServerAction = Async.Success(Unit)),
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ fun ChangeServerView(
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.ftue_auth_choose_server_title),
|
text = stringResource(id = R.string.screen_change_server_title),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.align(Alignment.CenterHorizontally),
|
.align(Alignment.CenterHorizontally),
|
||||||
|
|
@ -162,7 +162,7 @@ fun ChangeServerView(
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(8.dp))
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.ex_choose_server_subtitle),
|
text = stringResource(id = R.string.screen_change_server_subtitle),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
|
|
@ -172,7 +172,7 @@ fun ChangeServerView(
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(24.dp))
|
||||||
Text(
|
Text(
|
||||||
stringResource(StringR.string.hs_url),
|
stringResource(R.string.screen_change_server_form_header),
|
||||||
style = ElementTextStyles.Regular.formHeader,
|
style = ElementTextStyles.Regular.formHeader,
|
||||||
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
|
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||||
)
|
)
|
||||||
|
|
@ -202,7 +202,7 @@ fun ChangeServerView(
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
eventSink(ChangeServerEvents.SetServer(""))
|
eventSink(ChangeServerEvents.SetServer(""))
|
||||||
}, enabled = interactionEnabled) {
|
}, enabled = interactionEnabled) {
|
||||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.a11y_clear))
|
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.action_clear))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else null,
|
} else null,
|
||||||
|
|
@ -211,14 +211,13 @@ fun ChangeServerView(
|
||||||
if (invalidHomeserverError != null) {
|
if (invalidHomeserverError != null) {
|
||||||
Text(invalidHomeserverError.message(), color = MaterialTheme.colorScheme.error)
|
Text(invalidHomeserverError.message(), color = MaterialTheme.colorScheme.error)
|
||||||
} else {
|
} else {
|
||||||
val footerMessage = stringResource(StringR.string.server_selection_server_footer)
|
val footerMessage = stringResource(R.string.screen_change_server_form_notice, "")
|
||||||
val footerAction = stringResource(StringR.string.action_learn_more)
|
val footerAction = stringResource(StringR.string.action_learn_more)
|
||||||
val footerText = buildAnnotatedString {
|
val footerText = buildAnnotatedString {
|
||||||
val defaultColor = MaterialTheme.colorScheme.tertiary
|
val defaultColor = MaterialTheme.colorScheme.tertiary
|
||||||
withStyle(ParagraphStyle(textAlign = TextAlign.Start)) {
|
withStyle(ParagraphStyle(textAlign = TextAlign.Start)) {
|
||||||
withStyle(SpanStyle(color = defaultColor)) {
|
withStyle(SpanStyle(color = defaultColor)) {
|
||||||
append(footerMessage)
|
append(footerMessage)
|
||||||
append(" ")
|
|
||||||
}
|
}
|
||||||
val start = length
|
val start = length
|
||||||
withStyle(SpanStyle(color = LinkColor)) {
|
withStyle(SpanStyle(color = LinkColor)) {
|
||||||
|
|
@ -252,7 +251,7 @@ fun ChangeServerView(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.testTag(TestTags.changeServerContinue)
|
.testTag(TestTags.changeServerContinue)
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(id = StringR.string.login_continue), style = ElementTextStyles.Button)
|
Text(text = stringResource(id = R.string.screen_change_server_submit), style = ElementTextStyles.Button)
|
||||||
}
|
}
|
||||||
if (state.changeServerAction is Async.Success) {
|
if (state.changeServerAction is Async.Success) {
|
||||||
onChangeServerSuccess()
|
onChangeServerSuccess()
|
||||||
|
|
@ -284,8 +283,8 @@ internal fun SlidingSyncNotSupportedDialog(onLearnMoreClicked: () -> Unit, onDis
|
||||||
onSubmitClicked = onLearnMoreClicked,
|
onSubmitClicked = onLearnMoreClicked,
|
||||||
onCancelClicked = onDismiss,
|
onCancelClicked = onDismiss,
|
||||||
emphasizeSubmitButton = true,
|
emphasizeSubmitButton = true,
|
||||||
title = stringResource(StringR.string.server_selection_sliding_sync_alert_title),
|
title = stringResource(StringR.string.dialog_title_error),
|
||||||
content = stringResource(StringR.string.server_selection_sliding_sync_alert_message),
|
content = stringResource(R.string.screen_change_server_error_no_sliding_sync_message),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.login.impl.error
|
package io.element.android.features.login.impl.error
|
||||||
|
|
||||||
|
import io.element.android.features.login.impl.R
|
||||||
import io.element.android.libraries.matrix.api.auth.AuthErrorCode
|
import io.element.android.libraries.matrix.api.auth.AuthErrorCode
|
||||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||||
import io.element.android.libraries.matrix.api.auth.errorCode
|
import io.element.android.libraries.matrix.api.auth.errorCode
|
||||||
|
|
@ -24,10 +25,10 @@ import io.element.android.libraries.ui.strings.R.string as StringR
|
||||||
fun loginError(
|
fun loginError(
|
||||||
throwable: Throwable
|
throwable: Throwable
|
||||||
): Int {
|
): Int {
|
||||||
val authException = throwable as? AuthenticationException ?: return StringR.unknown_error
|
val authException = throwable as? AuthenticationException ?: return StringR.error_unknown
|
||||||
return when (authException.errorCode) {
|
return when (authException.errorCode) {
|
||||||
AuthErrorCode.FORBIDDEN -> StringR.auth_invalid_login_param
|
AuthErrorCode.FORBIDDEN -> R.string.screen_login_error_invalid_credentials
|
||||||
AuthErrorCode.USER_DEACTIVATED -> StringR.auth_invalid_login_deactivated_account
|
AuthErrorCode.USER_DEACTIVATED -> R.string.screen_login_error_deactivated_account
|
||||||
AuthErrorCode.UNKNOWN -> StringR.unknown_error
|
AuthErrorCode.UNKNOWN -> StringR.error_unknown
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import io.element.android.features.login.impl.R
|
||||||
import io.element.android.features.login.impl.error.loginError
|
import io.element.android.features.login.impl.error.loginError
|
||||||
import io.element.android.libraries.designsystem.ElementTextStyles
|
import io.element.android.libraries.designsystem.ElementTextStyles
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||||
|
|
@ -121,7 +122,7 @@ fun LoginRootView(
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
// Title
|
// Title
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.ftue_auth_welcome_back_title),
|
text = stringResource(id = R.string.screen_login_title),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
style = ElementTextStyles.Bold.title1,
|
style = ElementTextStyles.Bold.title1,
|
||||||
|
|
@ -172,7 +173,7 @@ internal fun ChangeServerSection(
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp),
|
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp),
|
||||||
text = stringResource(id = StringR.string.ftue_auth_sign_in_choose_server_header),
|
text = stringResource(id = R.string.screen_login_server_header),
|
||||||
style = ElementTextStyles.Regular.formHeader,
|
style = ElementTextStyles.Regular.formHeader,
|
||||||
)
|
)
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -233,7 +234,7 @@ internal fun LoginForm(
|
||||||
|
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(StringR.string.login_form_title),
|
text = stringResource(R.string.screen_login_form_header),
|
||||||
modifier = Modifier.padding(start = 16.dp),
|
modifier = Modifier.padding(start = 16.dp),
|
||||||
style = ElementTextStyles.Regular.formHeader
|
style = ElementTextStyles.Regular.formHeader
|
||||||
)
|
)
|
||||||
|
|
@ -247,7 +248,7 @@ internal fun LoginForm(
|
||||||
.onTabOrEnterKeyFocusNext(focusManager)
|
.onTabOrEnterKeyFocusNext(focusManager)
|
||||||
.testTag(TestTags.loginEmailUsername),
|
.testTag(TestTags.loginEmailUsername),
|
||||||
label = {
|
label = {
|
||||||
Text(text = stringResource(StringR.string.ex_login_username_hint))
|
Text(text = stringResource(R.string.screen_login_username_hint))
|
||||||
},
|
},
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
loginFieldState = it
|
loginFieldState = it
|
||||||
|
|
@ -267,7 +268,7 @@ internal fun LoginForm(
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
loginFieldState = ""
|
loginFieldState = ""
|
||||||
}) {
|
}) {
|
||||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.a11y_clear))
|
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.action_clear))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else null,
|
} else null,
|
||||||
|
|
@ -291,14 +292,14 @@ internal fun LoginForm(
|
||||||
eventSink(LoginRootEvents.SetPassword(it))
|
eventSink(LoginRootEvents.SetPassword(it))
|
||||||
},
|
},
|
||||||
label = {
|
label = {
|
||||||
Text(text = stringResource(StringR.string.login_signup_password_hint))
|
Text(text = stringResource(R.string.screen_login_password_hint))
|
||||||
},
|
},
|
||||||
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
|
||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
val image =
|
val image =
|
||||||
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
|
if (passwordVisible) Icons.Filled.Visibility else Icons.Filled.VisibilityOff
|
||||||
val description =
|
val description =
|
||||||
if (passwordVisible) stringResource(StringR.string.login_hide_password) else stringResource(StringR.string.login_show_password)
|
if (passwordVisible) stringResource(StringR.string.a11y_hide_password) else stringResource(StringR.string.a11y_show_password)
|
||||||
|
|
||||||
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
IconButton(onClick = { passwordVisible = !passwordVisible }) {
|
||||||
Icon(imageVector = image, description)
|
Icon(imageVector = image, description)
|
||||||
|
|
@ -324,7 +325,7 @@ internal fun LoginForm(
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.testTag(TestTags.loginContinue)
|
.testTag(TestTags.loginContinue)
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(StringR.string.login_continue), style = ElementTextStyles.Button)
|
Text(text = stringResource(R.string.screen_login_submit), style = ElementTextStyles.Button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@
|
||||||
package io.element.android.features.login.impl.error
|
package io.element.android.features.login.impl.error
|
||||||
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import io.element.android.features.login.impl.R
|
||||||
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||||
import io.element.android.libraries.ui.strings.R
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
class ErrorFormatterTests {
|
class ErrorFormatterTests {
|
||||||
|
|
||||||
|
|
@ -27,31 +28,31 @@ class ErrorFormatterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `loginError - invalid unknown error returns unknown error message`() {
|
fun `loginError - invalid unknown error returns unknown error message`() {
|
||||||
val error = Throwable("Some unknown error")
|
val error = Throwable("Some unknown error")
|
||||||
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
|
assertThat(loginError(error)).isEqualTo(StringR.string.error_unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `loginError - invalid auth error returns unknown error message`() {
|
fun `loginError - invalid auth error returns unknown error message`() {
|
||||||
val error = AuthenticationException.SlidingSyncNotAvailable("Some message. Also contains M_FORBIDDEN, but won't be parsed")
|
val error = AuthenticationException.SlidingSyncNotAvailable("Some message. Also contains M_FORBIDDEN, but won't be parsed")
|
||||||
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
|
assertThat(loginError(error)).isEqualTo(StringR.string.error_unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `loginError - unknown error returns unknown error message`() {
|
fun `loginError - unknown error returns unknown error message`() {
|
||||||
val error = AuthenticationException.Generic("M_UNKNOWN")
|
val error = AuthenticationException.Generic("M_UNKNOWN")
|
||||||
assertThat(loginError(error)).isEqualTo(R.string.unknown_error)
|
assertThat(loginError(error)).isEqualTo(StringR.string.error_unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `loginError - forbidden error returns incorrect credentials message`() {
|
fun `loginError - forbidden error returns incorrect credentials message`() {
|
||||||
val error = AuthenticationException.Generic("M_FORBIDDEN")
|
val error = AuthenticationException.Generic("M_FORBIDDEN")
|
||||||
assertThat(loginError(error)).isEqualTo(R.string.auth_invalid_login_param)
|
assertThat(loginError(error)).isEqualTo(R.string.screen_login_error_invalid_credentials)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `loginError - user_deactivated error returns deactivated account message`() {
|
fun `loginError - user_deactivated error returns deactivated account message`() {
|
||||||
val error = AuthenticationException.Generic("M_USER_DEACTIVATED")
|
val error = AuthenticationException.Generic("M_USER_DEACTIVATED")
|
||||||
assertThat(loginError(error)).isEqualTo(R.string.auth_invalid_login_deactivated_account)
|
assertThat(loginError(error)).isEqualTo(R.string.screen_login_error_deactivated_account)
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion loginError
|
// endregion loginError
|
||||||
|
|
|
||||||
|
|
@ -56,9 +56,9 @@ fun LogoutPreferenceView(
|
||||||
// Log out confirmation dialog
|
// Log out confirmation dialog
|
||||||
if (openDialog.value) {
|
if (openDialog.value) {
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
title = stringResource(id = StringR.string.action_sign_out),
|
title = stringResource(id = R.string.screen_signout_confirmation_dialog_title),
|
||||||
content = stringResource(id = StringR.string.action_sign_out_confirmation_simple),
|
content = stringResource(id = R.string.screen_signout_confirmation_dialog_content),
|
||||||
submitText = stringResource(id = StringR.string.action_sign_out),
|
submitText = stringResource(id = R.string.screen_signout_confirmation_dialog_submit),
|
||||||
onCancelClicked = {
|
onCancelClicked = {
|
||||||
openDialog.value = false
|
openDialog.value = false
|
||||||
},
|
},
|
||||||
|
|
@ -73,7 +73,7 @@ fun LogoutPreferenceView(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.logoutAction is Async.Loading) {
|
if (state.logoutAction is Async.Loading) {
|
||||||
ProgressDialog(text = "Login out...")
|
ProgressDialog(text = stringResource(id = R.string.screen_signout_in_progress_dialog_content))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,9 +81,9 @@ fun LogoutPreferenceView(
|
||||||
fun LogoutPreferenceContent(
|
fun LogoutPreferenceContent(
|
||||||
onClick: () -> Unit = {},
|
onClick: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
PreferenceCategory(title = stringResource(id = StringR.string.settings_general_title)) {
|
PreferenceCategory(title = stringResource(id = StringR.string.settings_title_general)) {
|
||||||
PreferenceText(
|
PreferenceText(
|
||||||
title = stringResource(id = StringR.string.action_sign_out),
|
title = stringResource(id = R.string.screen_signout_preference_item),
|
||||||
icon = Icons.Default.Logout,
|
icon = Icons.Default.Logout,
|
||||||
onClick = onClick
|
onClick = onClick
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ dependencies {
|
||||||
implementation(projects.libraries.matrixui)
|
implementation(projects.libraries.matrixui)
|
||||||
implementation(projects.libraries.designsystem)
|
implementation(projects.libraries.designsystem)
|
||||||
implementation(projects.libraries.textcomposer)
|
implementation(projects.libraries.textcomposer)
|
||||||
|
implementation(projects.libraries.uiStrings)
|
||||||
implementation(projects.libraries.dateformatter.api)
|
implementation(projects.libraries.dateformatter.api)
|
||||||
implementation(libs.coil.compose)
|
implementation(libs.coil.compose)
|
||||||
implementation(libs.datetime)
|
implementation(libs.datetime)
|
||||||
|
|
|
||||||
|
|
@ -20,20 +20,23 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Warning
|
import androidx.compose.material.icons.filled.Warning
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
|
||||||
|
|
||||||
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemEncryptedView(
|
fun TimelineItemEncryptedView(
|
||||||
content: TimelineItemEncryptedContent,
|
content: TimelineItemEncryptedContent,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = "Decryption error",
|
text = stringResource(id = StringR.string.common_decryption_error),
|
||||||
iconDescription = "Warning",
|
iconDescription = stringResource(id = StringR.string.dialog_title_warning),
|
||||||
icon = Icons.Default.Warning,
|
icon = Icons.Default.Warning,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -20,19 +20,22 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemRedactedContent
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
|
||||||
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemRedactedView(
|
fun TimelineItemRedactedView(
|
||||||
content: TimelineItemRedactedContent,
|
content: TimelineItemRedactedContent,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = "This message has been deleted",
|
text = stringResource(id = StringR.string.common_message_removed),
|
||||||
iconDescription = "Delete",
|
iconDescription = stringResource(id = StringR.string.common_message_removed),
|
||||||
icon = Icons.Default.Delete,
|
icon = Icons.Default.Delete,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -20,19 +20,22 @@ import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Info
|
import androidx.compose.material.icons.filled.Info
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemUnknownContent
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
|
||||||
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineItemUnknownView(
|
fun TimelineItemUnknownView(
|
||||||
content: TimelineItemUnknownContent,
|
content: TimelineItemUnknownContent,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
TimelineItemInformativeView(
|
TimelineItemInformativeView(
|
||||||
text = "Event not handled by EAX",
|
text = stringResource(id = StringR.string.common_unsupported_event),
|
||||||
iconDescription = "Info",
|
iconDescription = stringResource(id = StringR.string.dialog_title_warning),
|
||||||
icon = Icons.Default.Info,
|
icon = Icons.Default.Info,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ fun OnBoardingScreen(
|
||||||
.testTag(TestTags.onBoardingSignIn)
|
.testTag(TestTags.onBoardingSignIn)
|
||||||
.padding(top = 16.dp)
|
.padding(top = 16.dp)
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(id = StringR.string.login_splash_submit))
|
Text(text = stringResource(id = R.string.login_splash_submit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package io.element.android.features.onboarding.impl
|
package io.element.android.features.onboarding.impl
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import io.element.android.libraries.ui.strings.R as StringR
|
|
||||||
|
|
||||||
class SplashCarouselDataFactory {
|
class SplashCarouselDataFactory {
|
||||||
fun create(): SplashCarouselData {
|
fun create(): SplashCarouselData {
|
||||||
|
|
@ -32,8 +31,8 @@ class SplashCarouselDataFactory {
|
||||||
return SplashCarouselData(
|
return SplashCarouselData(
|
||||||
listOf(
|
listOf(
|
||||||
SplashCarouselData.Item(
|
SplashCarouselData.Item(
|
||||||
StringR.string.ftue_auth_carousel_secure_title,
|
R.string.ftue_auth_carousel_secure_title,
|
||||||
StringR.string.ftue_auth_carousel_secure_body,
|
R.string.ftue_auth_carousel_secure_body,
|
||||||
hero(
|
hero(
|
||||||
R.drawable.ic_splash_conversations,
|
R.drawable.ic_splash_conversations,
|
||||||
R.drawable.ic_splash_conversations_dark
|
R.drawable.ic_splash_conversations_dark
|
||||||
|
|
@ -41,20 +40,20 @@ class SplashCarouselDataFactory {
|
||||||
background(R.drawable.bg_carousel_page_1)
|
background(R.drawable.bg_carousel_page_1)
|
||||||
),
|
),
|
||||||
SplashCarouselData.Item(
|
SplashCarouselData.Item(
|
||||||
StringR.string.ftue_auth_carousel_control_title,
|
R.string.ftue_auth_carousel_control_title,
|
||||||
StringR.string.ftue_auth_carousel_control_body,
|
R.string.ftue_auth_carousel_control_body,
|
||||||
hero(R.drawable.ic_splash_control, R.drawable.ic_splash_control_dark),
|
hero(R.drawable.ic_splash_control, R.drawable.ic_splash_control_dark),
|
||||||
background(R.drawable.bg_carousel_page_2)
|
background(R.drawable.bg_carousel_page_2)
|
||||||
),
|
),
|
||||||
SplashCarouselData.Item(
|
SplashCarouselData.Item(
|
||||||
StringR.string.ftue_auth_carousel_encrypted_title,
|
R.string.ftue_auth_carousel_encrypted_title,
|
||||||
StringR.string.ftue_auth_carousel_encrypted_body,
|
R.string.ftue_auth_carousel_encrypted_body,
|
||||||
hero(R.drawable.ic_splash_secure, R.drawable.ic_splash_secure_dark),
|
hero(R.drawable.ic_splash_secure, R.drawable.ic_splash_secure_dark),
|
||||||
background(R.drawable.bg_carousel_page_3)
|
background(R.drawable.bg_carousel_page_3)
|
||||||
),
|
),
|
||||||
SplashCarouselData.Item(
|
SplashCarouselData.Item(
|
||||||
collaborationTitle(),
|
collaborationTitle(),
|
||||||
StringR.string.ftue_auth_carousel_workplace_body,
|
R.string.ftue_auth_carousel_workplace_body,
|
||||||
hero(
|
hero(
|
||||||
R.drawable.ic_splash_collaboration,
|
R.drawable.ic_splash_collaboration,
|
||||||
R.drawable.ic_splash_collaboration_dark
|
R.drawable.ic_splash_collaboration_dark
|
||||||
|
|
@ -68,7 +67,7 @@ class SplashCarouselDataFactory {
|
||||||
private fun collaborationTitle(): Int {
|
private fun collaborationTitle(): Int {
|
||||||
return when {
|
return when {
|
||||||
true -> R.string.cut_the_slack_from_teams
|
true -> R.string.cut_the_slack_from_teams
|
||||||
else -> StringR.string.ftue_auth_carousel_workplace_title
|
else -> R.string.ftue_auth_carousel_workplace_title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,5 +16,22 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- File to remove once the screen will be updated -->
|
||||||
|
|
||||||
<string name="cut_the_slack_from_teams" translatable="false">Cut the slack from teams.</string>
|
<string name="cut_the_slack_from_teams" translatable="false">Cut the slack from teams.</string>
|
||||||
|
|
||||||
|
<string name="login_splash_submit">Get started</string>
|
||||||
|
|
||||||
|
<string name="ftue_auth_carousel_secure_title">Own your conversations.</string>
|
||||||
|
<string name="ftue_auth_carousel_control_title">You\'re in control.</string>
|
||||||
|
<string name="ftue_auth_carousel_encrypted_title">Secure messaging.</string>
|
||||||
|
<string name="ftue_auth_carousel_workplace_title">Messaging for your team.</string>
|
||||||
|
|
||||||
|
<string name="ftue_auth_carousel_secure_body">Secure and independent communication that gives you the same level of privacy as a face-to-face conversation in your own home.</string>
|
||||||
|
<string name="ftue_auth_carousel_control_body">Choose where your conversations are kept, giving you control and independence. Connected via Matrix.</string>
|
||||||
|
<string name="ftue_auth_carousel_encrypted_body">End-to-end encrypted and no phone number required. No ads or datamining.</string>
|
||||||
|
|
||||||
|
<string name="ftue_auth_carousel_workplace_body">Element is also great for the workplace. It’s trusted by the world’s most secure organisations.</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ fun PreferencesRootView(
|
||||||
PreferenceView(
|
PreferenceView(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onBackPressed = onBackPressed,
|
onBackPressed = onBackPressed,
|
||||||
title = stringResource(id = StringR.string.settings)
|
title = stringResource(id = StringR.string.common_settings)
|
||||||
) {
|
) {
|
||||||
UserPreferences(state.myUser)
|
UserPreferences(state.myUser)
|
||||||
RageshakePreferencesView(
|
RageshakePreferencesView(
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package io.element.android.features.rageshake.api.crash
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import io.element.android.features.rageshake.api.R
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
|
|
@ -55,10 +56,10 @@ fun CrashDetectionContent(
|
||||||
onDismiss: () -> Unit = { },
|
onDismiss: () -> Unit = { },
|
||||||
) {
|
) {
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
title = stringResource(id = StringR.string.send_bug_report),
|
title = stringResource(id = StringR.string.action_report_bug),
|
||||||
content = stringResource(id = StringR.string.send_bug_report_app_crashed),
|
content = stringResource(id = R.string.crash_detection_dialog_content, /* TODO App name */ "Element"),
|
||||||
submitText = stringResource(id = StringR.string.yes),
|
submitText = stringResource(id = StringR.string.action_yes),
|
||||||
cancelText = stringResource(id = StringR.string.no),
|
cancelText = stringResource(id = StringR.string.action_no),
|
||||||
onCancelClicked = onNoClicked,
|
onCancelClicked = onNoClicked,
|
||||||
onSubmitClicked = onYesClicked,
|
onSubmitClicked = onYesClicked,
|
||||||
onDismiss = onDismiss,
|
onDismiss = onDismiss,
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import io.element.android.features.rageshake.api.R
|
||||||
import io.element.android.features.rageshake.api.screenshot.ImageResult
|
import io.element.android.features.rageshake.api.screenshot.ImageResult
|
||||||
import io.element.android.features.rageshake.api.screenshot.screenshot
|
import io.element.android.features.rageshake.api.screenshot.screenshot
|
||||||
import io.element.android.libraries.androidutils.hardware.vibrate
|
import io.element.android.libraries.androidutils.hardware.vibrate
|
||||||
|
|
@ -87,11 +88,11 @@ fun RageshakeDialogContent(
|
||||||
onYesClicked: () -> Unit = { },
|
onYesClicked: () -> Unit = { },
|
||||||
) {
|
) {
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
title = stringResource(id = StringR.string.send_bug_report),
|
title = stringResource(id = StringR.string.action_report_bug),
|
||||||
content = stringResource(id = StringR.string.send_bug_report_alert_message),
|
content = stringResource(id = R.string.rageshake_detection_dialog_content),
|
||||||
thirdButtonText = stringResource(id = StringR.string.action_disable),
|
thirdButtonText = stringResource(id = StringR.string.action_disable),
|
||||||
submitText = stringResource(id = StringR.string.yes),
|
submitText = stringResource(id = StringR.string.action_yes),
|
||||||
cancelText = stringResource(id = StringR.string.no),
|
cancelText = stringResource(id = StringR.string.action_no),
|
||||||
onCancelClicked = onNoClicked,
|
onCancelClicked = onNoClicked,
|
||||||
onThirdButtonClicked = onDisableClicked,
|
onThirdButtonClicked = onDisableClicked,
|
||||||
onSubmitClicked = onYesClicked,
|
onSubmitClicked = onYesClicked,
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,9 @@ fun RageshakePreferencesView(
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
PreferenceCategory(title = stringResource(id = StringR.string.send_bug_report)) {
|
PreferenceCategory(title = stringResource(id = StringR.string.action_report_bug)) {
|
||||||
PreferenceText(
|
PreferenceText(
|
||||||
title = stringResource(id = StringR.string.send_bug_report),
|
title = stringResource(id = StringR.string.action_report_bug),
|
||||||
icon = Icons.Default.BugReport,
|
icon = Icons.Default.BugReport,
|
||||||
onClick = onOpenRageshake
|
onClick = onOpenRageshake
|
||||||
)
|
)
|
||||||
|
|
@ -57,7 +57,7 @@ fun RageshakePreferencesView(
|
||||||
PreferenceCategory(title = stringResource(id = StringR.string.settings_rageshake)) {
|
PreferenceCategory(title = stringResource(id = StringR.string.settings_rageshake)) {
|
||||||
if (state.isSupported) {
|
if (state.isSupported) {
|
||||||
PreferenceSwitch(
|
PreferenceSwitch(
|
||||||
title = stringResource(id = StringR.string.send_bug_report_rage_shake),
|
title = stringResource(id = StringR.string.preference_rageshake),
|
||||||
isChecked = state.isEnabled,
|
isChecked = state.isEnabled,
|
||||||
onCheckedChange = ::onEnabledChanged
|
onCheckedChange = ::onEnabledChanged
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
import io.element.android.features.rageshake.impl.R
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.designsystem.components.LabelledCheckbox
|
import io.element.android.libraries.designsystem.components.LabelledCheckbox
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
||||||
|
|
@ -92,7 +93,7 @@ fun BugReportView(
|
||||||
val isFormEnabled = state.sending !is Async.Loading
|
val isFormEnabled = state.sending !is Async.Loading
|
||||||
// Title
|
// Title
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.send_bug_report),
|
text = stringResource(id = StringR.string.action_report_bug),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||||
|
|
@ -103,7 +104,7 @@ fun BugReportView(
|
||||||
)
|
)
|
||||||
// Form
|
// Form
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = StringR.string.send_bug_report_description),
|
text = stringResource(id = R.string.screen_bug_report_editor_description),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp),
|
.padding(horizontal = 16.dp, vertical = 16.dp),
|
||||||
|
|
@ -123,10 +124,10 @@ fun BugReportView(
|
||||||
.padding(top = 16.dp),
|
.padding(top = 16.dp),
|
||||||
enabled = isFormEnabled,
|
enabled = isFormEnabled,
|
||||||
label = {
|
label = {
|
||||||
Text(text = stringResource(id = StringR.string.send_bug_report_placeholder))
|
Text(text = stringResource(id = R.string.screen_bug_report_editor_placeholder))
|
||||||
},
|
},
|
||||||
supportingText = {
|
supportingText = {
|
||||||
Text(text = stringResource(id = StringR.string.send_bug_report_description_in_english))
|
Text(text = stringResource(id = R.string.screen_bug_report_editor_supporting))
|
||||||
},
|
},
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
descriptionFieldState = it
|
descriptionFieldState = it
|
||||||
|
|
@ -143,28 +144,28 @@ fun BugReportView(
|
||||||
checked = state.formState.sendLogs,
|
checked = state.formState.sendLogs,
|
||||||
onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) },
|
onCheckedChange = { eventSink(BugReportEvents.SetSendLog(it)) },
|
||||||
enabled = isFormEnabled,
|
enabled = isFormEnabled,
|
||||||
text = stringResource(id = StringR.string.send_bug_report_include_logs)
|
text = stringResource(id = R.string.screen_bug_report_include_logs)
|
||||||
)
|
)
|
||||||
if (state.hasCrashLogs) {
|
if (state.hasCrashLogs) {
|
||||||
LabelledCheckbox(
|
LabelledCheckbox(
|
||||||
checked = state.formState.sendCrashLogs,
|
checked = state.formState.sendCrashLogs,
|
||||||
onCheckedChange = { eventSink(BugReportEvents.SetSendCrashLog(it)) },
|
onCheckedChange = { eventSink(BugReportEvents.SetSendCrashLog(it)) },
|
||||||
enabled = isFormEnabled,
|
enabled = isFormEnabled,
|
||||||
text = stringResource(id = StringR.string.send_bug_report_include_crash_logs)
|
text = stringResource(id = R.string.screen_bug_report_include_crash_logs)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
LabelledCheckbox(
|
LabelledCheckbox(
|
||||||
checked = state.formState.canContact,
|
checked = state.formState.canContact,
|
||||||
onCheckedChange = { eventSink(BugReportEvents.SetCanContact(it)) },
|
onCheckedChange = { eventSink(BugReportEvents.SetCanContact(it)) },
|
||||||
enabled = isFormEnabled,
|
enabled = isFormEnabled,
|
||||||
text = stringResource(id = StringR.string.you_may_contact_me)
|
text = stringResource(id = R.string.screen_bug_report_contact_me)
|
||||||
)
|
)
|
||||||
if (state.screenshotUri != null) {
|
if (state.screenshotUri != null) {
|
||||||
LabelledCheckbox(
|
LabelledCheckbox(
|
||||||
checked = state.formState.sendScreenshot,
|
checked = state.formState.sendScreenshot,
|
||||||
onCheckedChange = { eventSink(BugReportEvents.SetSendScreenshot(it)) },
|
onCheckedChange = { eventSink(BugReportEvents.SetSendScreenshot(it)) },
|
||||||
enabled = isFormEnabled,
|
enabled = isFormEnabled,
|
||||||
text = stringResource(id = StringR.string.send_bug_report_include_screenshot)
|
text = stringResource(id = R.string.screen_bug_report_include_screenshot)
|
||||||
)
|
)
|
||||||
if (state.formState.sendScreenshot) {
|
if (state.formState.sendScreenshot) {
|
||||||
Box(
|
Box(
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
return when (val content = event.content) {
|
return when (val content = event.content) {
|
||||||
is MessageContent -> processMessageContents(content, senderDisplayName, isDmRoom)
|
is MessageContent -> processMessageContents(content, senderDisplayName, isDmRoom)
|
||||||
RedactedContent -> {
|
RedactedContent -> {
|
||||||
val message = context.getString(StringR.string.event_redacted)
|
val message = context.getString(StringR.string.common_message_removed)
|
||||||
if (!isDmRoom) {
|
if (!isDmRoom) {
|
||||||
prefix(message, senderDisplayName)
|
prefix(message, senderDisplayName)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -77,7 +77,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
content.body
|
content.body
|
||||||
}
|
}
|
||||||
is UnableToDecryptContent -> {
|
is UnableToDecryptContent -> {
|
||||||
val message = context.getString(StringR.string.encryption_information_decryption_error)
|
val message = context.getString(StringR.string.common_decryption_error)
|
||||||
if (!isDmRoom) {
|
if (!isDmRoom) {
|
||||||
prefix(message, senderDisplayName)
|
prefix(message, senderDisplayName)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -94,7 +94,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
processRoomStateChange(content, senderDisplayName, isOutgoing)
|
processRoomStateChange(content, senderDisplayName, isOutgoing)
|
||||||
}
|
}
|
||||||
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
|
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
|
||||||
prefixIfNeeded(context.getString(StringR.string.room_timeline_item_unsupported), senderDisplayName, isDmRoom)
|
prefixIfNeeded(context.getString(StringR.string.common_unsupported_event), senderDisplayName, isDmRoom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,19 +111,19 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
messageType.body
|
messageType.body
|
||||||
}
|
}
|
||||||
is VideoMessageType -> {
|
is VideoMessageType -> {
|
||||||
context.getString(StringR.string.sent_a_video)
|
context.getString(StringR.string.common_video)
|
||||||
}
|
}
|
||||||
is ImageMessageType -> {
|
is ImageMessageType -> {
|
||||||
context.getString(StringR.string.sent_an_image)
|
context.getString(StringR.string.common_image)
|
||||||
}
|
}
|
||||||
is FileMessageType -> {
|
is FileMessageType -> {
|
||||||
context.getString(StringR.string.sent_a_file)
|
context.getString(StringR.string.common_file)
|
||||||
}
|
}
|
||||||
is AudioMessageType -> {
|
is AudioMessageType -> {
|
||||||
context.getString(StringR.string.sent_an_audio_file)
|
context.getString(StringR.string.common_audio)
|
||||||
}
|
}
|
||||||
UnknownMessageType -> {
|
UnknownMessageType -> {
|
||||||
context.getString(StringR.string.unknown_message_content_type_error)
|
context.getString(StringR.string.common_unsupported_event)
|
||||||
}
|
}
|
||||||
is NoticeMessageType -> {
|
is NoticeMessageType -> {
|
||||||
messageType.body
|
messageType.body
|
||||||
|
|
@ -137,73 +137,73 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
val memberIsYou = userId == matrixClient.sessionId
|
val memberIsYou = userId == matrixClient.sessionId
|
||||||
return when (val change = membershipContent.change) {
|
return when (val change = membershipContent.change) {
|
||||||
MembershipChange.JOINED -> if (memberIsYou) {
|
MembershipChange.JOINED -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_join_by_you)
|
context.getString(R.string.state_event_room_join_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_join, userId.value)
|
context.getString(R.string.state_event_room_join, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.LEFT -> if (memberIsYou) {
|
MembershipChange.LEFT -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_leave_by_you)
|
context.getString(R.string.state_event_room_leave_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_leave, userId.value)
|
context.getString(R.string.state_event_room_leave, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
|
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_ban_by_you, userId.value)
|
context.getString(R.string.state_event_room_ban_by_you, userId.value)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_ban, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.UNBANNED -> if (senderIsYou) {
|
MembershipChange.UNBANNED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_unban_by_you, userId.value)
|
context.getString(R.string.state_event_room_unban_by_you, userId.value)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_unban, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.KICKED -> if (senderIsYou) {
|
MembershipChange.KICKED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_remove_by_you, userId.value)
|
context.getString(R.string.state_event_room_remove_by_you, userId.value)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_remove, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.INVITED -> if (senderIsYou) {
|
MembershipChange.INVITED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_invite_by_you, userId.value)
|
context.getString(R.string.state_event_room_invite_by_you, userId.value)
|
||||||
} else if (memberIsYou) {
|
} else if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_invite_you, senderDisplayName)
|
context.getString(R.string.state_event_room_invite_you, senderDisplayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_invite, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
|
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_invite_accepted_by_you)
|
context.getString(R.string.state_event_room_invite_accepted_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_invite_accepted, userId.value)
|
context.getString(R.string.state_event_room_invite_accepted, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.INVITATION_REJECTED -> if (memberIsYou) {
|
MembershipChange.INVITATION_REJECTED -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_reject_by_you)
|
context.getString(R.string.state_event_room_reject_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_reject, userId.value)
|
context.getString(R.string.state_event_room_reject, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
|
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_third_party_revoked_invite_by_you, userId.value)
|
context.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_third_party_revoked_invite, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.KNOCKED -> if (memberIsYou) {
|
MembershipChange.KNOCKED -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_knock_by_you)
|
context.getString(R.string.state_event_room_knock_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_knock, userId.value)
|
context.getString(R.string.state_event_room_knock, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
|
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_knock_accepted_by_you, userId.value)
|
context.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_knock_accepted, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
|
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_knock_retracted_by_you)
|
context.getString(R.string.state_event_room_knock_retracted_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_knock_retracted, userId.value)
|
context.getString(R.string.state_event_room_knock_retracted, userId.value)
|
||||||
}
|
}
|
||||||
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
|
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_knock_denied_by_you, userId.value)
|
context.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
|
||||||
} else if (memberIsYou) {
|
} else if (memberIsYou) {
|
||||||
context.getString(StringR.string.notice_room_knock_denied_you, senderDisplayName)
|
context.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_knock_denied, senderDisplayName, userId.value)
|
context.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Timber.v("Filtering timeline item for room membership: $membershipContent")
|
Timber.v("Filtering timeline item for room membership: $membershipContent")
|
||||||
|
|
@ -217,27 +217,27 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
is OtherState.RoomAvatar -> {
|
is OtherState.RoomAvatar -> {
|
||||||
val hasAvatarUrl = content.url != null
|
val hasAvatarUrl = content.url != null
|
||||||
when {
|
when {
|
||||||
senderIsYou && hasAvatarUrl -> context.getString(StringR.string.notice_room_avatar_changed_by_you)
|
senderIsYou && hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_changed_by_you)
|
||||||
senderIsYou && !hasAvatarUrl -> context.getString(StringR.string.notice_room_avatar_removed_by_you)
|
senderIsYou && !hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_removed_by_you)
|
||||||
!senderIsYou && hasAvatarUrl -> context.getString(StringR.string.notice_room_avatar_changed, senderDisplayName)
|
!senderIsYou && hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_changed, senderDisplayName)
|
||||||
else -> context.getString(StringR.string.notice_room_avatar_removed, senderDisplayName)
|
else -> context.getString(R.string.state_event_room_avatar_removed, senderDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is OtherState.RoomCreate -> {
|
is OtherState.RoomCreate -> {
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_created_by_you)
|
context.getString(R.string.state_event_room_created_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_created, senderDisplayName)
|
context.getString(R.string.state_event_room_created, senderDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is OtherState.RoomEncryption -> context.getString(StringR.string.encryption_enabled)
|
is OtherState.RoomEncryption -> context.getString(StringR.string.common_encryption_enabled)
|
||||||
is OtherState.RoomName -> {
|
is OtherState.RoomName -> {
|
||||||
val hasRoomName = content.name != null
|
val hasRoomName = content.name != null
|
||||||
when {
|
when {
|
||||||
senderIsYou && hasRoomName -> context.getString(StringR.string.notice_room_name_changed_by_you, content.name)
|
senderIsYou && hasRoomName -> context.getString(R.string.state_event_room_name_changed_by_you, content.name)
|
||||||
senderIsYou && !hasRoomName -> context.getString(StringR.string.notice_room_name_removed_by_you)
|
senderIsYou && !hasRoomName -> context.getString(R.string.state_event_room_name_removed_by_you)
|
||||||
!senderIsYou && hasRoomName -> context.getString(StringR.string.notice_room_name_changed, senderDisplayName, content.name)
|
!senderIsYou && hasRoomName -> context.getString(R.string.state_event_room_name_changed, senderDisplayName, content.name)
|
||||||
else -> context.getString(StringR.string.notice_room_name_removed, senderDisplayName)
|
else -> context.getString(R.string.state_event_room_name_removed, senderDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is OtherState.RoomThirdPartyInvite -> {
|
is OtherState.RoomThirdPartyInvite -> {
|
||||||
|
|
@ -246,18 +246,18 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_room_third_party_invite_by_you, content.displayName)
|
context.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_room_third_party_invite, senderDisplayName, content.displayName)
|
context.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is OtherState.RoomTopic -> {
|
is OtherState.RoomTopic -> {
|
||||||
val hasRoomTopic = content.topic != null
|
val hasRoomTopic = content.topic != null
|
||||||
when {
|
when {
|
||||||
senderIsYou && hasRoomTopic -> context.getString(StringR.string.notice_room_topic_changed_by_you, content.topic)
|
senderIsYou && hasRoomTopic -> context.getString(R.string.state_event_room_topic_changed_by_you, content.topic)
|
||||||
senderIsYou && !hasRoomTopic -> context.getString(StringR.string.notice_room_topic_removed_by_you)
|
senderIsYou && !hasRoomTopic -> context.getString(R.string.state_event_room_topic_removed_by_you)
|
||||||
!senderIsYou && hasRoomTopic -> context.getString(StringR.string.notice_room_topic_changed, senderDisplayName, content.topic)
|
!senderIsYou && hasRoomTopic -> context.getString(R.string.state_event_room_topic_changed, senderDisplayName, content.topic)
|
||||||
else -> context.getString(StringR.string.notice_room_topic_removed, senderDisplayName)
|
else -> context.getString(R.string.state_event_room_topic_removed, senderDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|
@ -277,35 +277,35 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
return when {
|
return when {
|
||||||
avatarChanged && displayNameChanged -> {
|
avatarChanged && displayNameChanged -> {
|
||||||
val message = processProfileChangeContent(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderDisplayName, senderIsYou)
|
val message = processProfileChangeContent(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderDisplayName, senderIsYou)
|
||||||
val avatarChangedToo = context.getString(StringR.string.notice_avatar_changed_too)
|
val avatarChangedToo = context.getString(R.string.state_event_avatar_changed_too)
|
||||||
"$message\n$avatarChangedToo"
|
"$message\n$avatarChangedToo"
|
||||||
}
|
}
|
||||||
displayNameChanged -> {
|
displayNameChanged -> {
|
||||||
if (displayName != null && prevDisplayName != null) {
|
if (displayName != null && prevDisplayName != null) {
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_display_name_changed_from_by_you, prevDisplayName, displayName)
|
context.getString(R.string.state_event_display_name_changed_from_by_you, prevDisplayName, displayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
|
context.getString(R.string.state_event_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
|
||||||
}
|
}
|
||||||
} else if (displayName != null) {
|
} else if (displayName != null) {
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_display_name_set_by_you, displayName)
|
context.getString(R.string.state_event_display_name_set_by_you, displayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_display_name_set, senderDisplayName, displayName)
|
context.getString(R.string.state_event_display_name_set, senderDisplayName, displayName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_display_name_removed_by_you, prevDisplayName)
|
context.getString(R.string.state_event_display_name_removed_by_you, prevDisplayName)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_display_name_removed, senderDisplayName, prevDisplayName)
|
context.getString(R.string.state_event_display_name_removed, senderDisplayName, prevDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
avatarChanged -> {
|
avatarChanged -> {
|
||||||
if (senderIsYou) {
|
if (senderIsYou) {
|
||||||
context.getString(StringR.string.notice_avatar_url_changed_by_you)
|
context.getString(R.string.state_event_avatar_url_changed_by_you)
|
||||||
} else {
|
} else {
|
||||||
context.getString(StringR.string.notice_avatar_url_changed, senderDisplayName)
|
context.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ fun RoomListContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val verificationCompleteMessage = stringResource(StringR.string.verification_conclusion_ok_self_notice_title)
|
val verificationCompleteMessage = stringResource(StringR.string.common_verification_complete)
|
||||||
LaunchedEffect(state.presentVerificationSuccessfulMessage) {
|
LaunchedEffect(state.presentVerificationSuccessfulMessage) {
|
||||||
if (state.presentVerificationSuccessfulMessage) {
|
if (state.presentVerificationSuccessfulMessage) {
|
||||||
snackbarHostState.showSnackbar(
|
snackbarHostState.showSnackbar(
|
||||||
|
|
@ -187,7 +187,7 @@ fun RoomListContent(
|
||||||
containerColor = MaterialTheme.colorScheme.primary,
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
onClick = onCreateRoomClicked
|
onClick = onCreateRoomClicked
|
||||||
) {
|
) {
|
||||||
Icon(resourceId = DrawableR.drawable.ic_edit_square, contentDescription = stringResource(id = StringR.string.a11y_create_message))
|
Icon(resourceId = DrawableR.drawable.ic_edit_square, contentDescription = stringResource(id = R.string.screen_roomlist_a11y_create_message))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
snackbarHost = {
|
snackbarHost = {
|
||||||
|
|
@ -219,7 +219,7 @@ internal fun RequestVerificationHeader(
|
||||||
) {
|
) {
|
||||||
Row {
|
Row {
|
||||||
Text(
|
Text(
|
||||||
stringResource(StringR.string.session_verification_banner_title),
|
stringResource(R.string.session_verification_banner_title),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
style = ElementTextStyles.Bold.body,
|
style = ElementTextStyles.Bold.body,
|
||||||
color = MaterialTheme.colorScheme.primary,
|
color = MaterialTheme.colorScheme.primary,
|
||||||
|
|
@ -232,14 +232,14 @@ internal fun RequestVerificationHeader(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(stringResource(StringR.string.session_verification_banner_message), style = ElementTextStyles.Regular.bodyMD)
|
Text(stringResource(R.string.session_verification_banner_message), style = ElementTextStyles.Regular.bodyMD)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
Button(
|
Button(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 7.dp),
|
contentPadding = PaddingValues(horizontal = 20.dp, vertical = 7.dp),
|
||||||
onClick = onVerifyClicked,
|
onClick = onVerifyClicked,
|
||||||
) {
|
) {
|
||||||
Text(stringResource(StringR.string.session_verification_start), style = ElementTextStyles.Button)
|
Text(stringResource(StringR.string.action_continue), style = ElementTextStyles.Button)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import io.element.android.features.roomlist.impl.R
|
||||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
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.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||||
|
|
@ -136,7 +137,7 @@ fun SearchRoomListTopBar(
|
||||||
},
|
},
|
||||||
placeholder = {
|
placeholder = {
|
||||||
Text(
|
Text(
|
||||||
text = "Search",
|
text = stringResource(id = StringR.string.action_search),
|
||||||
color = MaterialTheme.colorScheme.onBackground.copy(alpha = ContentAlpha.medium)
|
color = MaterialTheme.colorScheme.onBackground.copy(alpha = ContentAlpha.medium)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -207,7 +208,7 @@ private fun DefaultRoomListTopBar(
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
text = stringResource(id = StringR.string.all_chats)
|
text = stringResource(id = R.string.screen_roomlist_main_space_title)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
|
|
||||||
|
|
@ -182,13 +182,13 @@ class DefaultRoomLastMessageFormatterTests {
|
||||||
// Verify results of DM mode
|
// Verify results of DM mode
|
||||||
for ((type, result) in resultsInDm) {
|
for ((type, result) in resultsInDm) {
|
||||||
val expectedResult = when (type) {
|
val expectedResult = when (type) {
|
||||||
is VideoMessageType -> "Video."
|
is VideoMessageType -> "Video"
|
||||||
is AudioMessageType -> "Audio"
|
is AudioMessageType -> "Audio"
|
||||||
is ImageMessageType -> "Image."
|
is ImageMessageType -> "Image"
|
||||||
is FileMessageType -> "File"
|
is FileMessageType -> "File"
|
||||||
is EmoteMessageType -> "- $senderName ${type.body}"
|
is EmoteMessageType -> "- $senderName ${type.body}"
|
||||||
is TextMessageType, is NoticeMessageType -> body
|
is TextMessageType, is NoticeMessageType -> body
|
||||||
UnknownMessageType -> "Event type not handled by EAX"
|
UnknownMessageType -> "Unsupported event"
|
||||||
}
|
}
|
||||||
Truth.assertWithMessage("$type was not properly handled").that(result).isEqualTo(expectedResult)
|
Truth.assertWithMessage("$type was not properly handled").that(result).isEqualTo(expectedResult)
|
||||||
}
|
}
|
||||||
|
|
@ -197,13 +197,13 @@ class DefaultRoomLastMessageFormatterTests {
|
||||||
for ((type, result) in resultsInRoom) {
|
for ((type, result) in resultsInRoom) {
|
||||||
val string = result.toString()
|
val string = result.toString()
|
||||||
val expectedResult = when (type) {
|
val expectedResult = when (type) {
|
||||||
is VideoMessageType -> "$senderName: Video."
|
is VideoMessageType -> "$senderName: Video"
|
||||||
is AudioMessageType -> "$senderName: Audio"
|
is AudioMessageType -> "$senderName: Audio"
|
||||||
is ImageMessageType -> "$senderName: Image."
|
is ImageMessageType -> "$senderName: Image"
|
||||||
is FileMessageType -> "$senderName: File"
|
is FileMessageType -> "$senderName: File"
|
||||||
is EmoteMessageType -> "- $senderName ${type.body}"
|
is EmoteMessageType -> "- $senderName ${type.body}"
|
||||||
is TextMessageType, is NoticeMessageType -> "$senderName: $body"
|
is TextMessageType, is NoticeMessageType -> "$senderName: $body"
|
||||||
UnknownMessageType -> "$senderName: Event type not handled by EAX"
|
UnknownMessageType -> "$senderName: Unsupported event"
|
||||||
}
|
}
|
||||||
val shouldCreateAnnotatedString = when (type) {
|
val shouldCreateAnnotatedString = when (type) {
|
||||||
is VideoMessageType -> true
|
is VideoMessageType -> true
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@ fun SearchUserBar(
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
isMultiSelectionEnabled: Boolean,
|
isMultiSelectionEnabled: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
placeHolderTitle: String = stringResource(StringR.string.search_for_someone),
|
placeHolderTitle: String = stringResource(StringR.string.common_search_for_someone),
|
||||||
onActiveChanged: (Boolean) -> Unit = {},
|
onActiveChanged: (Boolean) -> Unit = {},
|
||||||
onTextChanged: (String) -> Unit = {},
|
onTextChanged: (String) -> Unit = {},
|
||||||
onUserSelected: (MatrixUser) -> Unit = {},
|
onUserSelected: (MatrixUser) -> Unit = {},
|
||||||
|
|
@ -154,7 +154,7 @@ fun SearchUserBar(
|
||||||
active && query.isNotEmpty() -> {
|
active && query.isNotEmpty() -> {
|
||||||
{
|
{
|
||||||
IconButton(onClick = { onTextChanged("") }) {
|
IconButton(onClick = { onTextChanged("") }) {
|
||||||
Icon(Icons.Default.Close, stringResource(StringR.string.a11y_clear))
|
Icon(Icons.Default.Close, stringResource(StringR.string.action_clear))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +162,7 @@ fun SearchUserBar(
|
||||||
{
|
{
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Search,
|
imageVector = Icons.Default.Search,
|
||||||
contentDescription = stringResource(StringR.string.search),
|
contentDescription = stringResource(StringR.string.action_search),
|
||||||
modifier = Modifier.alpha(0.4f), // FIXME align on Design system theme (removing alpha should be fine)
|
modifier = Modifier.alpha(0.4f), // FIXME align on Design system theme (removing alpha should be fine)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -111,16 +111,16 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier =
|
||||||
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.drawable.ic_verification_emoji
|
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.drawable.ic_verification_emoji
|
||||||
}
|
}
|
||||||
val titleTextId = when (verificationFlowStep) {
|
val titleTextId = when (verificationFlowStep) {
|
||||||
FlowStep.Initial -> StringR.string.verification_title_initial
|
FlowStep.Initial -> R.string.screen_session_verification_open_existing_session_title
|
||||||
FlowStep.Canceled -> StringR.string.verification_title_canceled
|
FlowStep.Canceled -> R.string.screen_session_verification_cancelled_title
|
||||||
FlowStep.AwaitingOtherDeviceResponse -> StringR.string.verification_title_waiting
|
FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_to_accept_title
|
||||||
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_title_verifying
|
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_title
|
||||||
}
|
}
|
||||||
val subtitleTextId = when (verificationFlowStep) {
|
val subtitleTextId = when (verificationFlowStep) {
|
||||||
FlowStep.Initial -> StringR.string.verification_subtitle_initial
|
FlowStep.Initial -> R.string.screen_session_verification_open_existing_session_subtitle
|
||||||
FlowStep.Canceled -> StringR.string.verification_subtitle_canceled
|
FlowStep.Canceled -> R.string.screen_session_verification_cancelled_subtitle
|
||||||
FlowStep.AwaitingOtherDeviceResponse -> StringR.string.verification_subtitle_waiting
|
FlowStep.AwaitingOtherDeviceResponse -> R.string.screen_session_verification_waiting_to_accept_subtitle
|
||||||
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> StringR.string.verification_subtitle_verifying
|
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_subtitle
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(modifier) {
|
Column(modifier) {
|
||||||
|
|
@ -216,22 +216,22 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
|
||||||
|
|
||||||
val isVerifying = (verificationViewState as? FlowStep.Verifying)?.state is Async.Loading<Unit>
|
val isVerifying = (verificationViewState as? FlowStep.Verifying)?.state is Async.Loading<Unit>
|
||||||
val positiveButtonTitle = when (verificationViewState) {
|
val positiveButtonTitle = when (verificationViewState) {
|
||||||
FlowStep.Initial -> StringR.string.verification_positive_button_initial
|
FlowStep.Initial -> R.string.screen_session_verification_positive_button_initial
|
||||||
FlowStep.Canceled -> StringR.string.verification_positive_button_canceled
|
FlowStep.Canceled -> R.string.screen_session_verification_positive_button_canceled
|
||||||
is FlowStep.Verifying -> {
|
is FlowStep.Verifying -> {
|
||||||
if (isVerifying) {
|
if (isVerifying) {
|
||||||
StringR.string.verification_positive_button_verifying_ongoing
|
R.string.screen_session_verification_positive_button_verifying_ongoing
|
||||||
} else {
|
} else {
|
||||||
StringR.string.verification_positive_button_verifying_start
|
R.string.screen_session_verification_they_match
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FlowStep.Ready -> StringR.string.verification_positive_button_ready
|
FlowStep.Ready -> R.string.screen_session_verification_positive_button_ready
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
val negativeButtonTitle = when (verificationViewState) {
|
val negativeButtonTitle = when (verificationViewState) {
|
||||||
FlowStep.Initial -> StringR.string.verification_negative_button_initial
|
FlowStep.Initial -> StringR.string.action_cancel
|
||||||
FlowStep.Canceled -> StringR.string.verification_negative_button_canceled
|
FlowStep.Canceled -> StringR.string.action_cancel
|
||||||
is FlowStep.Verifying -> StringR.string.verification_negative_button_verifying
|
is FlowStep.Verifying -> R.string.screen_session_verification_they_dont_match
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
val negativeButtonEnabled = !isVerifying
|
val negativeButtonEnabled = !isVerifying
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ fun BackButton(
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
imageVector: ImageVector = Icons.Default.ArrowBack,
|
imageVector: ImageVector = Icons.Default.ArrowBack,
|
||||||
contentDescription: String = stringResource(StringR.string.a11y_back),
|
contentDescription: String = stringResource(StringR.string.action_back),
|
||||||
enabled: Boolean = true
|
enabled: Boolean = true
|
||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ fun ConfirmationDialog(
|
||||||
onSubmitClicked: () -> Unit,
|
onSubmitClicked: () -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
submitText: String = stringResource(id = StringR.string.ok),
|
submitText: String = stringResource(id = StringR.string.action_ok),
|
||||||
cancelText: String = stringResource(id = StringR.string.action_cancel),
|
cancelText: String = stringResource(id = StringR.string.action_cancel),
|
||||||
thirdButtonText: String? = null,
|
thirdButtonText: String? = null,
|
||||||
emphasizeSubmitButton: Boolean = false,
|
emphasizeSubmitButton: Boolean = false,
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ fun ErrorDialog(
|
||||||
|
|
||||||
object ErrorDialogDefaults {
|
object ErrorDialogDefaults {
|
||||||
val title: String @Composable get() = stringResource(id = StringR.string.dialog_title_error)
|
val title: String @Composable get() = stringResource(id = StringR.string.dialog_title_error)
|
||||||
val submitText: String @Composable get() = stringResource(id = StringR.string.ok)
|
val submitText: String @Composable get() = stringResource(id = StringR.string.action_ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|
|
||||||
|
|
@ -249,28 +249,28 @@ class RichTextComposerLayout @JvmOverloads constructor(
|
||||||
private fun setupRichTextMenu() {
|
private fun setupRichTextMenu() {
|
||||||
addRichTextMenuItem(
|
addRichTextMenuItem(
|
||||||
R.drawable.ic_composer_bold,
|
R.drawable.ic_composer_bold,
|
||||||
StringR.string.rich_text_editor_format_bold,
|
R.string.rich_text_editor_format_bold,
|
||||||
ComposerAction.BOLD
|
ComposerAction.BOLD
|
||||||
) {
|
) {
|
||||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Bold)
|
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Bold)
|
||||||
}
|
}
|
||||||
addRichTextMenuItem(
|
addRichTextMenuItem(
|
||||||
R.drawable.ic_composer_italic,
|
R.drawable.ic_composer_italic,
|
||||||
StringR.string.rich_text_editor_format_italic,
|
R.string.rich_text_editor_format_italic,
|
||||||
ComposerAction.ITALIC
|
ComposerAction.ITALIC
|
||||||
) {
|
) {
|
||||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Italic)
|
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Italic)
|
||||||
}
|
}
|
||||||
addRichTextMenuItem(
|
addRichTextMenuItem(
|
||||||
R.drawable.ic_composer_underlined,
|
R.drawable.ic_composer_underlined,
|
||||||
StringR.string.rich_text_editor_format_underline,
|
R.string.rich_text_editor_format_underline,
|
||||||
ComposerAction.UNDERLINE
|
ComposerAction.UNDERLINE
|
||||||
) {
|
) {
|
||||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Underline)
|
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Underline)
|
||||||
}
|
}
|
||||||
addRichTextMenuItem(
|
addRichTextMenuItem(
|
||||||
R.drawable.ic_composer_strikethrough,
|
R.drawable.ic_composer_strikethrough,
|
||||||
StringR.string.rich_text_editor_format_strikethrough,
|
R.string.rich_text_editor_format_strikethrough,
|
||||||
ComposerAction.STRIKE_THROUGH
|
ComposerAction.STRIKE_THROUGH
|
||||||
) {
|
) {
|
||||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.StrikeThrough)
|
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.StrikeThrough)
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ private fun MessageComposerView.setup(isDarkMode: Boolean, composerMode: Message
|
||||||
}
|
}
|
||||||
editText.setTextColor(editTextColor)
|
editText.setTextColor(editTextColor)
|
||||||
editText.setHintTextColor(editTextColor)
|
editText.setHintTextColor(editTextColor)
|
||||||
editText.setHint(StringR.string.room_message_placeholder)
|
editText.setHint(R.string.rich_text_editor_composer_placeholder)
|
||||||
emojiButton?.isVisible = true
|
emojiButton?.isVisible = true
|
||||||
sendButton.isVisible = true
|
sendButton.isVisible = true
|
||||||
editText.maxLines = MessageComposerView.MAX_LINES_WHEN_COLLAPSED
|
editText.maxLines = MessageComposerView.MAX_LINES_WHEN_COLLAPSED
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_margin="@dimen/composer_attachment_margin"
|
android:layout_margin="@dimen/composer_attachment_margin"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:contentDescription="@string/option_send_files"
|
android:contentDescription="@string/a11y_send_files"
|
||||||
android:src="@drawable/ic_rich_composer_add"
|
android:src="@drawable/ic_rich_composer_add"
|
||||||
android:paddingStart="4dp"
|
android:paddingStart="4dp"
|
||||||
app:layout_constraintVertical_bias="1"
|
app:layout_constraintVertical_bias="1"
|
||||||
|
|
@ -143,7 +143,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintHeight_default="wrap"
|
app:layout_constraintHeight_default="wrap"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:hint="@string/room_message_placeholder"
|
android:hint="@string/rich_text_editor_composer_placeholder"
|
||||||
android:nextFocusLeft="@id/richTextComposerEditText"
|
android:nextFocusLeft="@id/richTextComposerEditText"
|
||||||
android:nextFocusUp="@id/richTextComposerEditText"
|
android:nextFocusUp="@id/richTextComposerEditText"
|
||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="12dp"
|
||||||
|
|
@ -162,7 +162,7 @@
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintHeight_default="wrap"
|
app:layout_constraintHeight_default="wrap"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:hint="@string/room_message_placeholder"
|
android:hint="@string/rich_text_editor_composer_placeholder"
|
||||||
android:nextFocusLeft="@id/plainTextComposerEditText"
|
android:nextFocusLeft="@id/plainTextComposerEditText"
|
||||||
android:nextFocusUp="@id/plainTextComposerEditText"
|
android:nextFocusUp="@id/plainTextComposerEditText"
|
||||||
android:layout_marginStart="12dp"
|
android:layout_marginStart="12dp"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue