fix(ui): partner invite flow polish — compact layout, share button, back affordances, secondary route styling (batch 7)
This commit is contained in:
parent
cc974661d3
commit
d109f7fcd0
|
|
@ -244,7 +244,10 @@ fun AppNavigation(
|
||||||
EmailInviteScreen(onNavigate = navigateRoute)
|
EmailInviteScreen(onNavigate = navigateRoute)
|
||||||
}
|
}
|
||||||
composable(route = AppRoute.ACCEPT_INVITE) {
|
composable(route = AppRoute.ACCEPT_INVITE) {
|
||||||
AcceptInviteScreen(onNavigate = navigateRoute)
|
AcceptInviteScreen(
|
||||||
|
onNavigate = navigateRoute,
|
||||||
|
onBack = navigateBackOrHome
|
||||||
|
)
|
||||||
}
|
}
|
||||||
composable(
|
composable(
|
||||||
route = AppRoute.INVITE_CONFIRM,
|
route = AppRoute.INVITE_CONFIRM,
|
||||||
|
|
@ -252,7 +255,8 @@ fun AppNavigation(
|
||||||
) {
|
) {
|
||||||
InviteConfirmScreen(
|
InviteConfirmScreen(
|
||||||
inviteCode = it.arguments?.getString("inviteCode") ?: "",
|
inviteCode = it.arguments?.getString("inviteCode") ?: "",
|
||||||
onNavigate = navigateRoute
|
onNavigate = navigateRoute,
|
||||||
|
onBack = navigateBackOrHome
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package app.closer.ui.pairing
|
package app.closer.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.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
|
@ -13,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.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
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
|
||||||
|
|
@ -46,10 +47,11 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
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.AnnotatedString
|
||||||
import androidx.compose.ui.text.input.OffsetMapping
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
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.OffsetMapping
|
||||||
import androidx.compose.ui.text.input.TransformedText
|
import androidx.compose.ui.text.input.TransformedText
|
||||||
import androidx.compose.ui.text.input.VisualTransformation
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
@ -69,6 +71,7 @@ import app.closer.ui.settings.SettingsSoft
|
||||||
@Composable
|
@Composable
|
||||||
fun AcceptInviteScreen(
|
fun AcceptInviteScreen(
|
||||||
onNavigate: (String) -> Unit = {},
|
onNavigate: (String) -> Unit = {},
|
||||||
|
onBack: () -> Unit = {},
|
||||||
viewModel: AcceptInviteViewModel = hiltViewModel()
|
viewModel: AcceptInviteViewModel = hiltViewModel()
|
||||||
) {
|
) {
|
||||||
val state by viewModel.uiState.collectAsState()
|
val state by viewModel.uiState.collectAsState()
|
||||||
|
|
@ -87,7 +90,7 @@ fun AcceptInviteScreen(
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = { onNavigate(AppRoute.CREATE_INVITE) }) {
|
IconButton(onClick = onBack) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
contentDescription = "Back",
|
contentDescription = "Back",
|
||||||
|
|
@ -114,11 +117,12 @@ fun AcceptInviteScreen(
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Enter the code",
|
"Enter the code",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = SettingsInk,
|
color = SettingsInk,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(6.dp))
|
||||||
Text(
|
Text(
|
||||||
"Ask your partner to share their 6-character invite code.",
|
"Ask your partner to share their 6-character invite code.",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
|
@ -126,7 +130,7 @@ fun AcceptInviteScreen(
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(36.dp))
|
Spacer(Modifier.height(28.dp))
|
||||||
|
|
||||||
InviteCodeEntryCard(
|
InviteCodeEntryCard(
|
||||||
value = state.code,
|
value = state.code,
|
||||||
|
|
@ -143,12 +147,13 @@ fun AcceptInviteScreen(
|
||||||
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus(); viewModel.lookupCode() })
|
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus(); viewModel.lookupCode() })
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(20.dp))
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
onClick = { focusManager.clearFocus(); viewModel.lookupCode() },
|
onClick = { focusManager.clearFocus(); viewModel.lookupCode() },
|
||||||
enabled = !state.isLoading && state.code.length == 6,
|
enabled = !state.isLoading && state.code.length == 6,
|
||||||
modifier = Modifier.fillMaxWidth().height(52.dp),
|
modifier = Modifier.fillMaxWidth().height(52.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = SettingsPrimary,
|
containerColor = SettingsPrimary,
|
||||||
contentColor = SettingsOnPrimary
|
contentColor = SettingsOnPrimary
|
||||||
|
|
@ -162,9 +167,12 @@ fun AcceptInviteScreen(
|
||||||
else Text("Continue", style = MaterialTheme.typography.labelLarge)
|
else Text("Continue", style = MaterialTheme.typography.labelLarge)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(28.dp))
|
||||||
|
|
||||||
TextButton(onClick = { onNavigate(AppRoute.CREATE_INVITE) }) {
|
TextButton(
|
||||||
|
onClick = { onNavigate(AppRoute.CREATE_INVITE) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Need to create an invite instead?",
|
"Need to create an invite instead?",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
|
@ -199,7 +207,7 @@ private fun InviteCodeEntryCard(
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(32.dp),
|
.padding(vertical = 28.dp, horizontal = 24.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package app.closer.ui.pairing
|
package app.closer.ui.pairing
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
|
@ -19,6 +20,7 @@ import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
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.material.icons.filled.ContentCopy
|
import androidx.compose.material.icons.filled.ContentCopy
|
||||||
|
import androidx.compose.material.icons.filled.Share
|
||||||
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.Card
|
||||||
|
|
@ -45,6 +47,7 @@ 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.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
@ -71,6 +74,7 @@ fun CreateInviteScreen(
|
||||||
val snackbar = remember { SnackbarHostState() }
|
val snackbar = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val clipboard = LocalClipboardManager.current
|
val clipboard = LocalClipboardManager.current
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
LaunchedEffect(state.navigateTo) {
|
LaunchedEffect(state.navigateTo) {
|
||||||
state.navigateTo?.let { onNavigate(it); viewModel.onNavigated() }
|
state.navigateTo?.let { onNavigate(it); viewModel.onNavigated() }
|
||||||
|
|
@ -79,6 +83,11 @@ fun CreateInviteScreen(
|
||||||
state.error?.let { snackbar.showSnackbar(it); viewModel.dismissError() }
|
state.error?.let { snackbar.showSnackbar(it); viewModel.dismissError() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val formattedCode = state.inviteCode?.chunked(3)?.joinToString(" – ")
|
||||||
|
val shareMessage = state.inviteCode?.let { code ->
|
||||||
|
"Join me on Closer! Here's my invite code: ${code.chunked(3).joinToString(" - ")}"
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(snackbar) },
|
snackbarHost = { SnackbarHost(snackbar) },
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
|
|
@ -107,28 +116,30 @@ fun CreateInviteScreen(
|
||||||
.padding(padding)
|
.padding(padding)
|
||||||
.padding(horizontal = 28.dp),
|
.padding(horizontal = 28.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
if (state.isLoading) {
|
if (state.isLoading) {
|
||||||
|
Spacer(Modifier.height(160.dp))
|
||||||
CircularProgressIndicator(modifier = Modifier.size(40.dp))
|
CircularProgressIndicator(modifier = Modifier.size(40.dp))
|
||||||
} else if (state.inviteCode != null) {
|
} else if (state.inviteCode != null) {
|
||||||
Spacer(Modifier.height(48.dp))
|
Spacer(Modifier.height(24.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Invite your person",
|
"Invite your person",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = SettingsInk,
|
color = SettingsInk,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(8.dp))
|
Spacer(Modifier.height(6.dp))
|
||||||
Text(
|
Text(
|
||||||
"Share this code with your partner. They'll enter it to connect.",
|
"Share this code with your partner so they can connect with you.",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = SettingsMuted,
|
color = SettingsMuted,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(40.dp))
|
Spacer(Modifier.height(28.dp))
|
||||||
|
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -140,11 +151,11 @@ fun CreateInviteScreen(
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(32.dp),
|
.padding(vertical = 28.dp, horizontal = 24.dp),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = state.inviteCode!!.chunked(3).joinToString(" – "),
|
text = formattedCode!!,
|
||||||
style = MaterialTheme.typography.displaySmall,
|
style = MaterialTheme.typography.displaySmall,
|
||||||
color = SettingsPrimaryDeep,
|
color = SettingsPrimaryDeep,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
|
|
@ -153,27 +164,60 @@ fun CreateInviteScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(20.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
Button(
|
Row(
|
||||||
onClick = {
|
modifier = Modifier.fillMaxWidth(),
|
||||||
clipboard.setText(AnnotatedString(state.inviteCode!!))
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
scope.launch { snackbar.showSnackbar("Code copied!") }
|
|
||||||
},
|
|
||||||
modifier = Modifier.fillMaxWidth().height(52.dp),
|
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
colors = ButtonDefaults.buttonColors(
|
|
||||||
containerColor = SettingsPrimary,
|
|
||||||
contentColor = SettingsOnPrimary
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
Row(
|
Button(
|
||||||
horizontalArrangement = Arrangement.Center,
|
onClick = {
|
||||||
verticalAlignment = Alignment.CenterVertically
|
clipboard.setText(AnnotatedString(state.inviteCode!!))
|
||||||
|
scope.launch { snackbar.showSnackbar("Code copied!") }
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f).height(52.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = SettingsPrimary,
|
||||||
|
contentColor = SettingsOnPrimary
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Filled.ContentCopy, contentDescription = null, modifier = Modifier.size(18.dp))
|
Row(
|
||||||
Spacer(Modifier.width(8.dp))
|
horizontalArrangement = Arrangement.Center,
|
||||||
Text("Copy code", style = MaterialTheme.typography.labelLarge)
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.ContentCopy, contentDescription = null, modifier = Modifier.size(18.dp))
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
|
Text("Copy", style = MaterialTheme.typography.labelLarge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shareMessage?.let { message ->
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||||
|
type = "text/plain"
|
||||||
|
putExtra(Intent.EXTRA_TEXT, message)
|
||||||
|
}
|
||||||
|
val chooser = Intent.createChooser(intent, "Share invite code")
|
||||||
|
context.startActivity(chooser)
|
||||||
|
},
|
||||||
|
modifier = Modifier.weight(1f).height(52.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
|
colors = ButtonDefaults.buttonColors(
|
||||||
|
containerColor = SettingsPrimary.copy(alpha = 0.16f),
|
||||||
|
contentColor = SettingsPrimaryDeep
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Icon(Icons.Filled.Share, contentDescription = null, modifier = Modifier.size(18.dp))
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
|
Text("Share", style = MaterialTheme.typography.labelLarge)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -186,20 +230,20 @@ fun CreateInviteScreen(
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(32.dp))
|
Spacer(Modifier.height(28.dp))
|
||||||
|
|
||||||
TextButton(onClick = { onNavigate(AppRoute.ACCEPT_INVITE) }) {
|
TextButton(
|
||||||
|
onClick = { onNavigate(AppRoute.ACCEPT_INVITE) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Partner already has a code? Accept instead",
|
"Partner already has a code? Accept instead",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = SettingsPrimaryDeep
|
color = SettingsPrimaryDeep
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(32.dp))
|
|
||||||
} else {
|
} else {
|
||||||
// Empty / error state when no code is available
|
Spacer(Modifier.height(160.dp))
|
||||||
Spacer(Modifier.height(48.dp))
|
|
||||||
Text(
|
Text(
|
||||||
"No invite code yet",
|
"No invite code yet",
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,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.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
|
@ -36,6 +37,7 @@ 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.text.font.FontWeight
|
||||||
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
|
||||||
|
|
@ -46,12 +48,14 @@ import app.closer.ui.settings.SettingsMuted
|
||||||
import app.closer.ui.settings.SettingsOnPrimary
|
import app.closer.ui.settings.SettingsOnPrimary
|
||||||
import app.closer.ui.settings.SettingsPrimary
|
import app.closer.ui.settings.SettingsPrimary
|
||||||
import app.closer.ui.settings.SettingsPrimaryDeep
|
import app.closer.ui.settings.SettingsPrimaryDeep
|
||||||
|
import app.closer.ui.settings.SettingsSoft
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun InviteConfirmScreen(
|
fun InviteConfirmScreen(
|
||||||
inviteCode: String,
|
inviteCode: String,
|
||||||
onNavigate: (String) -> Unit = {},
|
onNavigate: (String) -> Unit = {},
|
||||||
|
onBack: () -> Unit = {},
|
||||||
viewModel: InviteConfirmViewModel = hiltViewModel()
|
viewModel: InviteConfirmViewModel = hiltViewModel()
|
||||||
) {
|
) {
|
||||||
val state by viewModel.uiState.collectAsState()
|
val state by viewModel.uiState.collectAsState()
|
||||||
|
|
@ -64,6 +68,8 @@ fun InviteConfirmScreen(
|
||||||
state.error?.let { snackbar.showSnackbar(it); viewModel.dismissError() }
|
state.error?.let { snackbar.showSnackbar(it); viewModel.dismissError() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val formattedCode = inviteCode.chunked(3).joinToString(" – ")
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(snackbar) },
|
snackbarHost = { SnackbarHost(snackbar) },
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
|
|
@ -72,7 +78,7 @@ fun InviteConfirmScreen(
|
||||||
TopAppBar(
|
TopAppBar(
|
||||||
title = {},
|
title = {},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = { onNavigate(AppRoute.ACCEPT_INVITE) }) {
|
IconButton(onClick = onBack) {
|
||||||
Icon(
|
Icon(
|
||||||
Icons.AutoMirrored.Filled.ArrowBack,
|
Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
contentDescription = "Back",
|
contentDescription = "Back",
|
||||||
|
|
@ -92,12 +98,13 @@ fun InviteConfirmScreen(
|
||||||
.padding(padding)
|
.padding(padding)
|
||||||
.padding(horizontal = 28.dp),
|
.padding(horizontal = 28.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center
|
verticalArrangement = Arrangement.Top
|
||||||
) {
|
) {
|
||||||
if (state.isLoading) {
|
if (state.isLoading) {
|
||||||
|
Spacer(Modifier.height(160.dp))
|
||||||
CircularProgressIndicator(modifier = Modifier.size(40.dp))
|
CircularProgressIndicator(modifier = Modifier.size(40.dp))
|
||||||
} else {
|
} else {
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(24.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"♡",
|
"♡",
|
||||||
|
|
@ -105,15 +112,16 @@ fun InviteConfirmScreen(
|
||||||
color = SettingsPrimaryDeep
|
color = SettingsPrimaryDeep
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(20.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Pair with ${state.inviterName}?",
|
"Pair with ${state.inviterName}?",
|
||||||
style = MaterialTheme.typography.headlineMedium,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
color = SettingsInk,
|
color = SettingsInk,
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
)
|
)
|
||||||
Spacer(Modifier.height(12.dp))
|
Spacer(Modifier.height(6.dp))
|
||||||
Text(
|
Text(
|
||||||
"Once you confirm, you'll be connected and can start exploring questions together.",
|
"Once you confirm, you'll be connected and can start exploring questions together.",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
|
@ -121,10 +129,10 @@ fun InviteConfirmScreen(
|
||||||
textAlign = TextAlign.Center
|
textAlign = TextAlign.Center
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(Modifier.height(24.dp))
|
Spacer(Modifier.height(28.dp))
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
"Code: $inviteCode",
|
"Invite code $formattedCode",
|
||||||
style = MaterialTheme.typography.labelLarge,
|
style = MaterialTheme.typography.labelLarge,
|
||||||
color = SettingsMuted
|
color = SettingsMuted
|
||||||
)
|
)
|
||||||
|
|
@ -135,6 +143,7 @@ fun InviteConfirmScreen(
|
||||||
onClick = viewModel::confirmPairing,
|
onClick = viewModel::confirmPairing,
|
||||||
enabled = !state.isConfirming,
|
enabled = !state.isConfirming,
|
||||||
modifier = Modifier.fillMaxWidth().height(56.dp),
|
modifier = Modifier.fillMaxWidth().height(56.dp),
|
||||||
|
shape = RoundedCornerShape(16.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = SettingsPrimary,
|
containerColor = SettingsPrimary,
|
||||||
contentColor = SettingsOnPrimary
|
contentColor = SettingsOnPrimary
|
||||||
|
|
@ -150,15 +159,16 @@ fun InviteConfirmScreen(
|
||||||
|
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
|
|
||||||
TextButton(onClick = { onNavigate(AppRoute.ACCEPT_INVITE) }) {
|
TextButton(
|
||||||
|
onClick = { onNavigate(AppRoute.ACCEPT_INVITE) },
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
Text(
|
Text(
|
||||||
"That's not right — go back",
|
"That's not right — enter a different code",
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color = SettingsPrimaryDeep
|
color = SettingsPrimaryDeep
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(Modifier.height(32.dp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue