refactor: update AcceptInviteScreen with theme-consistent visuals and layout

This commit is contained in:
null 2026-06-16 19:14:06 -05:00
parent 99ff77a357
commit a870b17801
1 changed files with 103 additions and 11 deletions

View File

@ -1,6 +1,7 @@
package com.couplesconnect.app.ui.pairing
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@ -12,6 +13,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
@ -19,12 +21,13 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
@ -40,10 +43,15 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.input.OffsetMapping
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TransformedText
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@ -55,6 +63,7 @@ import com.couplesconnect.app.ui.settings.SettingsMuted
import com.couplesconnect.app.ui.settings.SettingsOnPrimary
import com.couplesconnect.app.ui.settings.SettingsPrimary
import com.couplesconnect.app.ui.settings.SettingsPrimaryDeep
import com.couplesconnect.app.ui.settings.SettingsSoft
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -119,22 +128,16 @@ fun AcceptInviteScreen(
Spacer(Modifier.height(36.dp))
OutlinedTextField(
InviteCodeEntryCard(
value = state.code,
onValueChange = viewModel::updateCode,
label = { Text("Invite code") },
placeholder = { Text("ABC123") },
singleLine = true,
isError = state.error != null,
supportingText = state.error?.let { error -> { Text(error, color = SettingsDanger) } },
error = state.error,
modifier = Modifier.fillMaxWidth(),
textStyle = MaterialTheme.typography.headlineSmall.copy(
textAlign = TextAlign.Center,
letterSpacing = androidx.compose.ui.unit.TextUnit.Unspecified
),
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Text,
keyboardType = KeyboardType.Ascii,
capitalization = KeyboardCapitalization.Characters,
autoCorrectEnabled = false,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus(); viewModel.lookupCode() })
@ -171,3 +174,92 @@ fun AcceptInviteScreen(
}
}
}
@Composable
private fun InviteCodeEntryCard(
value: String,
onValueChange: (String) -> Unit,
isError: Boolean,
error: String?,
modifier: Modifier = Modifier,
keyboardOptions: KeyboardOptions,
keyboardActions: KeyboardActions
) {
Column(
modifier = modifier,
horizontalAlignment = Alignment.CenterHorizontally
) {
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = SettingsSoft
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(32.dp),
contentAlignment = Alignment.Center
) {
BasicTextField(
value = value,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth(),
singleLine = true,
textStyle = MaterialTheme.typography.displaySmall.copy(
color = if (isError) SettingsDanger else SettingsPrimaryDeep,
textAlign = TextAlign.Center
),
cursorBrush = SolidColor(SettingsPrimaryDeep),
keyboardOptions = keyboardOptions,
keyboardActions = keyboardActions,
visualTransformation = InviteCodeVisualTransformation,
decorationBox = { innerTextField ->
if (value.isBlank()) {
Text(
text = "ABC 123",
style = MaterialTheme.typography.displaySmall,
color = SettingsPrimaryDeep.copy(alpha = 0.36f),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
}
innerTextField()
}
)
}
}
if (error != null) {
Spacer(Modifier.height(8.dp))
Text(
text = error,
style = MaterialTheme.typography.bodySmall,
color = SettingsDanger,
textAlign = TextAlign.Center
)
}
}
}
private object InviteCodeVisualTransformation : VisualTransformation {
override fun filter(text: AnnotatedString): TransformedText {
val raw = text.text
val transformed = raw.chunked(3).joinToString(" ")
val mapping = object : OffsetMapping {
override fun originalToTransformed(offset: Int): Int =
if (offset <= 3) offset else offset + 3
override fun transformedToOriginal(offset: Int): Int =
when {
offset <= 3 -> offset
offset <= 6 -> 3
else -> offset - 3
}.coerceIn(0, raw.length)
}
return TransformedText(AnnotatedString(transformed), mapping)
}
}