refactor: update AcceptInviteScreen with theme-consistent visuals and layout
This commit is contained in:
parent
99ff77a357
commit
a870b17801
|
|
@ -1,6 +1,7 @@
|
||||||
package com.couplesconnect.app.ui.pairing
|
package com.couplesconnect.app.ui.pairing
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
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.safeDrawingPadding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
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.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
|
|
@ -40,10 +43,15 @@ import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
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.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
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.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
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.SettingsOnPrimary
|
||||||
import com.couplesconnect.app.ui.settings.SettingsPrimary
|
import com.couplesconnect.app.ui.settings.SettingsPrimary
|
||||||
import com.couplesconnect.app.ui.settings.SettingsPrimaryDeep
|
import com.couplesconnect.app.ui.settings.SettingsPrimaryDeep
|
||||||
|
import com.couplesconnect.app.ui.settings.SettingsSoft
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -119,22 +128,16 @@ fun AcceptInviteScreen(
|
||||||
|
|
||||||
Spacer(Modifier.height(36.dp))
|
Spacer(Modifier.height(36.dp))
|
||||||
|
|
||||||
OutlinedTextField(
|
InviteCodeEntryCard(
|
||||||
value = state.code,
|
value = state.code,
|
||||||
onValueChange = viewModel::updateCode,
|
onValueChange = viewModel::updateCode,
|
||||||
label = { Text("Invite code") },
|
|
||||||
placeholder = { Text("ABC123") },
|
|
||||||
singleLine = true,
|
|
||||||
isError = state.error != null,
|
isError = state.error != null,
|
||||||
supportingText = state.error?.let { error -> { Text(error, color = SettingsDanger) } },
|
error = state.error,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
textStyle = MaterialTheme.typography.headlineSmall.copy(
|
|
||||||
textAlign = TextAlign.Center,
|
|
||||||
letterSpacing = androidx.compose.ui.unit.TextUnit.Unspecified
|
|
||||||
),
|
|
||||||
keyboardOptions = KeyboardOptions(
|
keyboardOptions = KeyboardOptions(
|
||||||
keyboardType = KeyboardType.Text,
|
keyboardType = KeyboardType.Ascii,
|
||||||
capitalization = KeyboardCapitalization.Characters,
|
capitalization = KeyboardCapitalization.Characters,
|
||||||
|
autoCorrectEnabled = false,
|
||||||
imeAction = ImeAction.Done
|
imeAction = ImeAction.Done
|
||||||
),
|
),
|
||||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus(); viewModel.lookupCode() })
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue