@@ -9,6 +9,7 @@ package io.element.android.features.securebackup.impl.setup.views
99
1010import androidx.compose.foundation.background
1111import androidx.compose.foundation.layout.Arrangement
12+ import androidx.compose.foundation.layout.Box
1213import androidx.compose.foundation.layout.Column
1314import androidx.compose.foundation.layout.Row
1415import androidx.compose.foundation.layout.fillMaxWidth
@@ -24,8 +25,10 @@ import androidx.compose.ui.Alignment
2425import androidx.compose.ui.ExperimentalComposeUiApi
2526import androidx.compose.ui.Modifier
2627import androidx.compose.ui.autofill.AutofillType
28+ import androidx.compose.ui.draw.alpha
2729import androidx.compose.ui.draw.clip
2830import androidx.compose.ui.res.stringResource
31+ import androidx.compose.ui.text.font.FontFamily
2932import androidx.compose.ui.text.input.ImeAction
3033import androidx.compose.ui.text.input.KeyboardType
3134import androidx.compose.ui.text.input.VisualTransformation
@@ -88,42 +91,38 @@ private fun RecoveryKeyStaticContent(
8891 state : RecoveryKeyViewState ,
8992 onClick : (() -> Unit )? ,
9093) {
91- Row (
94+ Box (
9295 modifier = Modifier
93- .fillMaxWidth()
94- .clip(RoundedCornerShape (14 .dp))
95- .background(
96- color = ElementTheme .colors.bgSubtleSecondary,
97- shape = RoundedCornerShape (14 .dp)
98- )
99- .clickableIfNotNull(onClick)
100- .padding(horizontal = 16 .dp, vertical = 16 .dp),
101- horizontalArrangement = Arrangement .spacedBy(8 .dp)
96+ .fillMaxWidth()
97+ .clip(RoundedCornerShape (10 .dp))
98+ .background(
99+ color = ElementTheme .colors.bgSubtleSecondary,
100+ )
101+ .clickableIfNotNull(onClick)
102+ .padding(horizontal = 16 .dp, vertical = 11 .dp),
103+ contentAlignment = Alignment .Center ,
102104 ) {
103105 if (state.formattedRecoveryKey != null ) {
104- Text (
105- text = state.formattedRecoveryKey,
106- modifier = Modifier .weight(1f ),
107- )
108- Icon (
109- imageVector = CompoundIcons .Copy (),
110- contentDescription = stringResource(id = CommonStrings .action_copy),
111- tint = ElementTheme .colors.iconSecondary,
106+ RecoveryKeyWithCopy (
107+ recoveryKey = state.formattedRecoveryKey,
108+ alpha = 1f ,
112109 )
113110 } else {
111+ // Use an invisible recovery key to ensure that the Box size is correct.
112+ val fakeFormattedRecoveryKey = List (12 ) { " XXXX" }.joinToString(" " )
113+ RecoveryKeyWithCopy (
114+ recoveryKey = fakeFormattedRecoveryKey,
115+ alpha = 0f ,
116+ )
114117 Row (
115118 verticalAlignment = Alignment .CenterVertically ,
116- horizontalArrangement = Arrangement .Center ,
117- modifier = Modifier
118- .fillMaxWidth()
119- .padding(vertical = 11 .dp)
120119 ) {
121120 if (state.inProgress) {
122121 CircularProgressIndicator (
123122 modifier = Modifier
124- .progressSemantics()
125- .padding(end = 8 .dp)
126- .size(16 .dp),
123+ .progressSemantics()
124+ .padding(end = 8 .dp)
125+ .size(16 .dp),
127126 color = ElementTheme .colors.textPrimary,
128127 strokeWidth = 1.5 .dp,
129128 )
@@ -144,6 +143,31 @@ private fun RecoveryKeyStaticContent(
144143 }
145144}
146145
146+ @Composable
147+ private fun RecoveryKeyWithCopy (
148+ recoveryKey : String ,
149+ alpha : Float ,
150+ ) {
151+ Row (
152+ modifier = Modifier
153+ .fillMaxWidth()
154+ .alpha(alpha),
155+ horizontalArrangement = Arrangement .spacedBy(8 .dp),
156+ ) {
157+ Text (
158+ text = recoveryKey,
159+ color = ElementTheme .colors.textSecondary,
160+ style = ElementTheme .typography.fontBodyLgRegular.copy(fontFamily = FontFamily .Monospace ),
161+ modifier = Modifier .weight(1f ),
162+ )
163+ Icon (
164+ imageVector = CompoundIcons .Copy (),
165+ contentDescription = stringResource(id = CommonStrings .action_copy),
166+ tint = ElementTheme .colors.iconSecondary,
167+ )
168+ }
169+ }
170+
147171@OptIn(ExperimentalComposeUiApi ::class )
148172@Composable
149173private fun RecoveryKeyFormContent (
@@ -160,12 +184,12 @@ private fun RecoveryKeyFormContent(
160184 }
161185 TextField (
162186 modifier = Modifier
163- .fillMaxWidth()
164- .testTag(TestTags .recoveryKey)
165- .autofill(
166- autofillTypes = listOf (AutofillType .Password ),
167- onFill = { onChange(it) },
168- ),
187+ .fillMaxWidth()
188+ .testTag(TestTags .recoveryKey)
189+ .autofill(
190+ autofillTypes = listOf (AutofillType .Password ),
191+ onFill = { onChange(it) },
192+ ),
169193 minLines = 2 ,
170194 value = state.formattedRecoveryKey.orEmpty(),
171195 onValueChange = onChange,
0 commit comments