feat: add CategoryGlyph component, DesireSync polish, UI refinements across screens
This commit is contained in:
parent
85bb8d9f69
commit
d135b306aa
|
|
@ -21,7 +21,7 @@ class MainActivity : ComponentActivity() {
|
|||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
AppNavigation(startDestination = app.closer.core.navigation.AppRoute.PLAY)
|
||||
AppNavigation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import androidx.compose.foundation.background
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -12,6 +14,7 @@ import androidx.compose.foundation.layout.heightIn
|
|||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
|
|
@ -30,6 +33,7 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
|
|
@ -41,6 +45,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.domain.model.LocalAnswer
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
import app.closer.ui.components.EmptyState
|
||||
import app.closer.ui.questions.displayCategoryName
|
||||
|
||||
|
|
@ -157,6 +162,7 @@ private fun AnswerHistoryContent(
|
|||
}
|
||||
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
private fun AnswerHistoryCard(
|
||||
answer: LocalAnswer,
|
||||
|
|
@ -170,47 +176,62 @@ private fun AnswerHistoryCard(
|
|||
colors = CardDefaults.cardColors(containerColor = Color.White),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp)
|
||||
) {
|
||||
Column(
|
||||
Row(
|
||||
modifier = Modifier.padding(17.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
HistoryPill(if (answer.isRevealed) "Revealed" else "Private")
|
||||
HistoryPill(answer.category.displayCategoryName())
|
||||
}
|
||||
Text(
|
||||
text = answer.questionText,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = Color(0xFF261D2E),
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
CategoryGlyph(
|
||||
categoryId = answer.category,
|
||||
modifier = Modifier.size(46.dp),
|
||||
size = 46.dp,
|
||||
iconSize = 22.dp
|
||||
)
|
||||
Text(
|
||||
text = if (answer.isRevealed) answer.revealSummary() else "Saved privately. Tap to reveal.",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = Color(0xFF5A5060),
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
FlowRow(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
HistoryPill(if (answer.isRevealed) "Revealed" else "Private")
|
||||
HistoryPill(answer.category.displayCategoryName())
|
||||
}
|
||||
Text(
|
||||
text = if (answer.isRevealed) "Opened" else "Private",
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = Color(0xFF56306F),
|
||||
fontWeight = FontWeight.SemiBold
|
||||
text = answer.questionText,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
color = Color(0xFF261D2E),
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
TextButton(
|
||||
onClick = onDelete,
|
||||
modifier = Modifier.heightIn(min = 48.dp)
|
||||
Text(
|
||||
text = if (answer.isRevealed) answer.revealSummary() else "Saved privately. Tap to reveal.",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = Color(0xFF5A5060),
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
Text(
|
||||
text = "Remove",
|
||||
color = Color(0xFF8D2D35)
|
||||
text = if (answer.isRevealed) "Opened" else "Private",
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = Color(0xFF56306F),
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
TextButton(
|
||||
onClick = onDelete,
|
||||
modifier = Modifier.heightIn(min = 48.dp)
|
||||
) {
|
||||
Text(
|
||||
text = "Remove",
|
||||
color = Color(0xFF8D2D35)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
|
|
@ -47,6 +48,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.ui.components.StatusGlyph
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
|
|
@ -97,7 +99,11 @@ fun ForgotPasswordScreen(
|
|||
|
||||
if (state.sent) {
|
||||
Spacer(Modifier.height(48.dp))
|
||||
Text("✓", style = MaterialTheme.typography.displayMedium, color = AuthPrimaryDeep)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Check,
|
||||
tint = AuthPrimaryDeep,
|
||||
container = AuthPrimary.copy(alpha = 0.16f)
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
"Reset email sent",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,239 @@
|
|||
package app.closer.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Chat
|
||||
import androidx.compose.material.icons.filled.AttachMoney
|
||||
import androidx.compose.material.icons.filled.CalendarToday
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.People
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Psychology
|
||||
import androidx.compose.material.icons.filled.QuestionAnswer
|
||||
import androidx.compose.material.icons.filled.Shield
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material.icons.filled.Sync
|
||||
import androidx.compose.material.icons.filled.Timeline
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material.icons.filled.Warning
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
|
||||
data class GlyphStyle(
|
||||
val icon: ImageVector,
|
||||
val tint: Color,
|
||||
val container: Color
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun CategoryGlyph(
|
||||
categoryId: String,
|
||||
modifier: Modifier = Modifier,
|
||||
iconName: String? = null,
|
||||
locked: Boolean = false,
|
||||
size: Dp = 48.dp,
|
||||
iconSize: Dp = 23.dp
|
||||
) {
|
||||
val style = categoryGlyphStyle(categoryId = categoryId, iconName = iconName, locked = locked)
|
||||
|
||||
Surface(
|
||||
modifier = modifier.size(size),
|
||||
shape = RoundedCornerShape((size.value * 0.36f).dp),
|
||||
color = style.container
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
imageVector = style.icon,
|
||||
contentDescription = null,
|
||||
tint = style.tint,
|
||||
modifier = Modifier.size(iconSize)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StatusGlyph(
|
||||
icon: ImageVector,
|
||||
modifier: Modifier = Modifier,
|
||||
tint: Color = CloserPalette.PurpleDeep,
|
||||
container: Color = CloserPalette.PurpleMist,
|
||||
size: Dp = 72.dp,
|
||||
iconSize: Dp = 34.dp,
|
||||
shadowElevation: Dp = 0.dp
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier.size(size),
|
||||
shape = RoundedCornerShape((size.value * 0.34f).dp),
|
||||
color = container,
|
||||
shadowElevation = shadowElevation
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = tint,
|
||||
modifier = Modifier.size(iconSize)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ResultGlyph(
|
||||
isPositive: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
isClose: Boolean = false,
|
||||
size: Dp = 32.dp
|
||||
) {
|
||||
val icon = when {
|
||||
isPositive -> Icons.Filled.Check
|
||||
isClose -> Icons.Filled.Timeline
|
||||
else -> Icons.Filled.Close
|
||||
}
|
||||
val tint = when {
|
||||
isPositive -> CloserPalette.Evergreen
|
||||
isClose -> CloserPalette.Gold
|
||||
else -> CloserPalette.Danger
|
||||
}
|
||||
val container = when {
|
||||
isPositive -> CloserPalette.Evergreen.copy(alpha = 0.12f)
|
||||
isClose -> CloserPalette.Gold.copy(alpha = 0.12f)
|
||||
else -> CloserPalette.Danger.copy(alpha = 0.12f)
|
||||
}
|
||||
|
||||
StatusGlyph(
|
||||
icon = icon,
|
||||
modifier = modifier,
|
||||
tint = tint,
|
||||
container = container,
|
||||
size = size,
|
||||
iconSize = (size.value * 0.58f).dp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun categoryGlyphStyle(
|
||||
categoryId: String,
|
||||
iconName: String? = null,
|
||||
locked: Boolean = false
|
||||
): GlyphStyle {
|
||||
if (locked) {
|
||||
return GlyphStyle(
|
||||
icon = Icons.Filled.Lock,
|
||||
tint = MaterialTheme.colorScheme.outline,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
}
|
||||
|
||||
val key = (iconName ?: categoryId).lowercase().trim()
|
||||
return when (key) {
|
||||
"communication", "chat", "question", "questions" -> GlyphStyle(
|
||||
icon = Icons.AutoMirrored.Filled.Chat,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
"emotional_intimacy", "intimacy", "heart" -> GlyphStyle(
|
||||
icon = Icons.Filled.Favorite,
|
||||
tint = CloserPalette.PinkAccentDeep,
|
||||
container = CloserPalette.PinkMist
|
||||
)
|
||||
"physical_intimacy", "sex_and_desire", "sexual_preferences", "desire", "sex" -> GlyphStyle(
|
||||
icon = Icons.Filled.FavoriteBorder,
|
||||
tint = CloserPalette.Romantic,
|
||||
container = CloserPalette.Romantic.copy(alpha = 0.12f)
|
||||
)
|
||||
"trust", "rebuilding_trust", "privacy" -> GlyphStyle(
|
||||
icon = Icons.Filled.Shield,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleGlow
|
||||
)
|
||||
"conflict", "conflict_repair", "repair" -> GlyphStyle(
|
||||
icon = Icons.Filled.Sync,
|
||||
tint = CloserPalette.PurpleRich,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
"future", "timeline" -> GlyphStyle(
|
||||
icon = Icons.Filled.Timeline,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleSoft
|
||||
)
|
||||
"money", "payments" -> GlyphStyle(
|
||||
icon = Icons.Filled.AttachMoney,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
"home_life", "home" -> GlyphStyle(
|
||||
icon = Icons.Filled.Home,
|
||||
tint = CloserPalette.PurpleRich,
|
||||
container = CloserPalette.PurpleGlow
|
||||
)
|
||||
"gratitude", "star" -> GlyphStyle(
|
||||
icon = Icons.Filled.Star,
|
||||
tint = CloserPalette.PinkAccentDeep,
|
||||
container = CloserPalette.PinkMist
|
||||
)
|
||||
"parenting", "family", "people" -> GlyphStyle(
|
||||
icon = Icons.Filled.People,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleSoft
|
||||
)
|
||||
"date_night", "date", "calendar" -> GlyphStyle(
|
||||
icon = Icons.Filled.CalendarToday,
|
||||
tint = CloserPalette.PinkAccentDeep,
|
||||
container = CloserPalette.PinkMist
|
||||
)
|
||||
"fun", "play" -> GlyphStyle(
|
||||
icon = Icons.Filled.PlayArrow,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleGlow
|
||||
)
|
||||
"stress", "difficult_conversations", "boundaries" -> GlyphStyle(
|
||||
icon = Icons.Filled.Warning,
|
||||
tint = CloserPalette.Danger,
|
||||
container = CloserPalette.Danger.copy(alpha = 0.10f)
|
||||
)
|
||||
"values", "marriage" -> GlyphStyle(
|
||||
icon = Icons.Filled.QuestionAnswer,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
"profile", "person" -> GlyphStyle(
|
||||
icon = Icons.Filled.Person,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
"reveal", "visibility" -> GlyphStyle(
|
||||
icon = Icons.Filled.Visibility,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleGlow
|
||||
)
|
||||
"predict", "psychology" -> GlyphStyle(
|
||||
icon = Icons.Filled.Psychology,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleGlow
|
||||
)
|
||||
else -> GlyphStyle(
|
||||
icon = Icons.Filled.Star,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,11 @@ import androidx.compose.foundation.layout.size
|
|||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material.icons.filled.Sync
|
||||
import androidx.compose.material.icons.filled.Visibility
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
|
|
@ -41,7 +46,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
|
@ -49,6 +53,7 @@ import app.closer.core.navigation.AppRoute
|
|||
import app.closer.domain.model.ChoiceAnswerConfigImpl
|
||||
import app.closer.domain.model.Question
|
||||
import app.closer.domain.repository.QuestionRepository
|
||||
import app.closer.ui.components.StatusGlyph
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
import app.closer.ui.theme.closerBackgroundBrush
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
|
|
@ -305,10 +310,10 @@ private fun DSIntroScreen(playerNumber: Int, total: Int, onReady: () -> Unit) {
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = if (playerNumber == 1) "🔥" else "💜",
|
||||
fontSize = 56.sp,
|
||||
textAlign = TextAlign.Center
|
||||
StatusGlyph(
|
||||
icon = if (playerNumber == 1) Icons.Filled.FavoriteBorder else Icons.Filled.Visibility,
|
||||
tint = CloserPalette.Romantic,
|
||||
container = CloserPalette.Romantic.copy(alpha = 0.12f)
|
||||
)
|
||||
Spacer(Modifier.height(20.dp))
|
||||
Surface(shape = RoundedCornerShape(999.dp), color = CloserPalette.Romantic.copy(alpha = 0.14f)) {
|
||||
|
|
@ -358,7 +363,11 @@ private fun DSHandoffScreen(onReady: () -> Unit) {
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text("🤝", fontSize = 56.sp, textAlign = TextAlign.Center)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Sync,
|
||||
tint = CloserPalette.Romantic,
|
||||
container = CloserPalette.Romantic.copy(alpha = 0.12f)
|
||||
)
|
||||
Spacer(Modifier.height(20.dp))
|
||||
Text(
|
||||
text = "Pass the phone!",
|
||||
|
|
@ -510,10 +519,12 @@ private fun DSRevealScreen(
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Text(
|
||||
text = if (matches.isEmpty()) "🤍" else "🔥",
|
||||
fontSize = 56.sp,
|
||||
textAlign = TextAlign.Center
|
||||
StatusGlyph(
|
||||
icon = if (matches.isEmpty()) Icons.Filled.FavoriteBorder else Icons.Filled.Favorite,
|
||||
tint = CloserPalette.Romantic,
|
||||
container = CloserPalette.Romantic.copy(alpha = 0.12f),
|
||||
size = 82.dp,
|
||||
iconSize = 40.dp
|
||||
)
|
||||
Text(
|
||||
text = if (matches.isEmpty()) "Nothing in common this round" else "${matches.size} shared desire${if (matches.size != 1) "s" else ""}",
|
||||
|
|
@ -599,7 +610,13 @@ private fun DesireMatchCard(match: DesireMatch) {
|
|||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text("❤️", fontSize = 20.sp)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Favorite,
|
||||
tint = CloserPalette.Romantic,
|
||||
container = CloserPalette.Romantic.copy(alpha = 0.12f),
|
||||
size = 34.dp,
|
||||
iconSize = 18.dp
|
||||
)
|
||||
Text(
|
||||
text = match.femaleQ.text,
|
||||
style = MaterialTheme.typography.bodyLarge.copy(fontWeight = FontWeight.Medium),
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.domain.model.Question
|
||||
import app.closer.domain.model.QuestionCategory
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
import app.closer.ui.questions.displayCategoryName
|
||||
|
||||
@Composable
|
||||
|
|
@ -566,6 +567,12 @@ private fun CategoryMiniCard(
|
|||
modifier = Modifier.padding(15.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
CategoryGlyph(
|
||||
categoryId = item.category.id,
|
||||
iconName = item.category.iconName,
|
||||
size = 42.dp,
|
||||
iconSize = 20.dp
|
||||
)
|
||||
Text(
|
||||
text = item.category.displayName.ifBlank { item.category.id.displayCategoryName() },
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Psychology
|
||||
import androidx.compose.material.icons.filled.Sync
|
||||
import androidx.compose.material.icons.filled.Timeline
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
|
|
@ -40,7 +45,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
|
@ -52,6 +56,8 @@ import app.closer.domain.model.Question
|
|||
import app.closer.domain.model.ScaleAnswerConfigImpl
|
||||
import app.closer.domain.model.ThisOrThatAnswerConfigImpl
|
||||
import app.closer.domain.repository.QuestionRepository
|
||||
import app.closer.ui.components.ResultGlyph
|
||||
import app.closer.ui.components.StatusGlyph
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
import app.closer.ui.theme.closerBackgroundBrush
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
|
|
@ -306,7 +312,11 @@ private fun PlayerIntroScreen(playerNumber: Int, total: Int, onReady: () -> Unit
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(text = if (playerNumber == 1) "👤" else "🔮", fontSize = 56.sp, textAlign = TextAlign.Center)
|
||||
StatusGlyph(
|
||||
icon = if (playerNumber == 1) Icons.Filled.Person else Icons.Filled.Psychology,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
Spacer(Modifier.height(20.dp))
|
||||
Surface(shape = RoundedCornerShape(999.dp), color = CloserPalette.PurpleMist) {
|
||||
Text(
|
||||
|
|
@ -358,7 +368,11 @@ private fun HandoffScreen(onReady: () -> Unit) {
|
|||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text("🎉", fontSize = 56.sp, textAlign = TextAlign.Center)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Sync,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist
|
||||
)
|
||||
Spacer(Modifier.height(20.dp))
|
||||
Text(
|
||||
text = "Pass the phone!",
|
||||
|
|
@ -566,10 +580,10 @@ private fun RevealScreen(
|
|||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (result.isMatch) "✓" else if (result.isClose) "≈" else "✗",
|
||||
fontSize = 28.sp,
|
||||
color = accentColor
|
||||
ResultGlyph(
|
||||
isPositive = result.isMatch,
|
||||
isClose = result.isClose,
|
||||
size = 38.dp
|
||||
)
|
||||
Text(
|
||||
text = if (result.isMatch) "Match!" else if (result.isClose) "So close!" else "Not quite",
|
||||
|
|
@ -678,7 +692,13 @@ private fun CompleteScreen(
|
|||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
Text("🎯", fontSize = 56.sp, textAlign = TextAlign.Center)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Timeline,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist,
|
||||
size = 82.dp,
|
||||
iconSize = 40.dp
|
||||
)
|
||||
Text(
|
||||
text = "$score / $total",
|
||||
style = MaterialTheme.typography.displaySmall.copy(fontWeight = FontWeight.Bold),
|
||||
|
|
@ -743,10 +763,10 @@ private fun BreakdownRow(result: HowWellResult) {
|
|||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = if (result.isMatch) "✓" else if (result.isClose) "≈" else "✗",
|
||||
fontSize = 18.sp,
|
||||
color = if (result.isMatch) matchColor else if (result.isClose) closeColor else missColor
|
||||
ResultGlyph(
|
||||
isPositive = result.isMatch,
|
||||
isClose = result.isClose,
|
||||
size = 28.dp
|
||||
)
|
||||
Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
|
||||
Text(
|
||||
|
|
@ -910,9 +930,9 @@ private fun ScaleInput(
|
|||
// ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
|
||||
private fun scoreLabel(score: Int, total: Int): String = when {
|
||||
score == total -> "Mind reader! 🤯"
|
||||
score >= total * 0.8 -> "You really know each other 💜"
|
||||
score == total -> "Perfect read"
|
||||
score >= total * 0.8 -> "You really know each other"
|
||||
score >= total * 0.6 -> "Pretty good!"
|
||||
score >= total * 0.4 -> "Getting there!"
|
||||
else -> "Room to grow 🌱"
|
||||
else -> "Room to grow"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.FavoriteBorder
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
|
|
@ -44,6 +45,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.ui.components.StatusGlyph
|
||||
import app.closer.ui.settings.SettingsBackgroundBrush
|
||||
import app.closer.ui.settings.SettingsInk
|
||||
import app.closer.ui.settings.SettingsMuted
|
||||
|
|
@ -109,10 +111,10 @@ fun InviteConfirmScreen(
|
|||
} else {
|
||||
Spacer(Modifier.height(24.dp))
|
||||
|
||||
Text(
|
||||
"♡",
|
||||
style = MaterialTheme.typography.displayMedium,
|
||||
color = SettingsPrimaryDeep
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.FavoriteBorder,
|
||||
tint = SettingsPrimaryDeep,
|
||||
container = SettingsSoft
|
||||
)
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowForward
|
|||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material.icons.filled.Favorite
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material3.Button
|
||||
|
|
@ -39,6 +40,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
import app.closer.ui.theme.closerBackgroundBrush
|
||||
import app.closer.ui.theme.closerBrandGlyphBrush
|
||||
|
|
@ -261,15 +263,12 @@ private fun DesireSyncCard(
|
|||
horizontalArrangement = Arrangement.spacedBy(14.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = CloserPalette.Romantic.copy(alpha = 0.12f),
|
||||
modifier = Modifier.size(52.dp)
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Text(text = "🔥", style = MaterialTheme.typography.titleMedium)
|
||||
}
|
||||
}
|
||||
CategoryGlyph(
|
||||
categoryId = "sex_and_desire",
|
||||
modifier = Modifier.size(52.dp),
|
||||
size = 52.dp,
|
||||
iconSize = 25.dp
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
|
|
@ -290,13 +289,24 @@ private fun DesireSyncCard(
|
|||
shape = RoundedCornerShape(999.dp),
|
||||
color = CloserPalette.Romantic.copy(alpha = 0.12f)
|
||||
) {
|
||||
Text(
|
||||
text = "🔒 Premium",
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = 10.dp, vertical = 4.dp),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = CloserPalette.Romantic,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Lock,
|
||||
contentDescription = null,
|
||||
tint = CloserPalette.Romantic,
|
||||
modifier = Modifier.size(13.dp)
|
||||
)
|
||||
Text(
|
||||
text = "Premium",
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = CloserPalette.Romantic,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Text(
|
||||
|
|
@ -335,18 +345,12 @@ private fun HowWellCard(
|
|||
horizontalArrangement = Arrangement.spacedBy(14.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = CloserPalette.Romantic.copy(alpha = 0.12f),
|
||||
modifier = Modifier.size(52.dp)
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Text(
|
||||
text = "💜",
|
||||
style = MaterialTheme.typography.titleMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
CategoryGlyph(
|
||||
categoryId = "predict",
|
||||
modifier = Modifier.size(52.dp),
|
||||
size = 52.dp,
|
||||
iconSize = 25.dp
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.heightIn
|
|||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
|
|
@ -42,6 +43,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.domain.model.Question
|
||||
import app.closer.domain.model.QuestionCategory
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
|
||||
@Composable
|
||||
fun QuestionCategoryScreen(
|
||||
|
|
@ -168,21 +170,39 @@ private fun CategoryHero(
|
|||
modifier = modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
|
||||
color = Color(0xFF261D2E),
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = category?.description
|
||||
?: "Browse prompts for this kind of conversation.",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = Color(0xFF5A5060),
|
||||
maxLines = 3,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(14.dp),
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
CategoryGlyph(
|
||||
categoryId = category?.id ?: title,
|
||||
iconName = category?.iconName,
|
||||
modifier = Modifier.size(58.dp),
|
||||
size = 58.dp,
|
||||
iconSize = 28.dp
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.headlineLarge.copy(fontWeight = FontWeight.SemiBold),
|
||||
color = Color(0xFF261D2E),
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = category?.description
|
||||
?: "Browse prompts for this kind of conversation.",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = Color(0xFF5A5060),
|
||||
maxLines = 3,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.heightIn
|
|||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
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.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
|
|
@ -44,6 +45,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.domain.model.QuestionCategory
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
|
||||
private enum class PackFilter(val label: String) {
|
||||
ALL("All"),
|
||||
|
|
@ -226,6 +228,13 @@ private fun QuestionPackCard(
|
|||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
CategoryGlyph(
|
||||
categoryId = item.category.id,
|
||||
iconName = item.category.iconName,
|
||||
locked = item.isLocked,
|
||||
modifier = Modifier.size(50.dp),
|
||||
size = 50.dp
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.spacedBy(6.dp)
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ import androidx.compose.foundation.lazy.items
|
|||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowForward
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Star
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
|
|
@ -41,6 +39,7 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.core.navigation.AppRoute
|
||||
import app.closer.domain.model.QuestionCategory
|
||||
import app.closer.ui.components.CategoryGlyph
|
||||
import app.closer.ui.questions.displayCategoryName
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
import app.closer.ui.theme.closerBackgroundBrush
|
||||
|
|
@ -257,20 +256,13 @@ private fun CategoryCard(
|
|||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
color = if (item.isLocked) CloserPalette.PurpleMist else MaterialTheme.colorScheme.secondaryContainer,
|
||||
modifier = Modifier.size(48.dp)
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
Icon(
|
||||
imageVector = if (item.isLocked) Icons.Default.Lock else Icons.Filled.Star,
|
||||
contentDescription = null,
|
||||
tint = if (item.isLocked) MaterialTheme.colorScheme.outline else CloserPalette.PinkAccentDeep,
|
||||
modifier = Modifier.size(22.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
CategoryGlyph(
|
||||
categoryId = item.category.id,
|
||||
iconName = item.category.iconName,
|
||||
locked = item.isLocked,
|
||||
modifier = Modifier.size(48.dp),
|
||||
size = 48.dp
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import androidx.compose.foundation.layout.navigationBarsPadding
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
|
|
@ -39,8 +41,9 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import app.closer.ui.components.StatusGlyph
|
||||
import app.closer.ui.theme.CloserPalette
|
||||
|
||||
@HiltViewModel
|
||||
class WheelCompleteViewModel @Inject constructor(
|
||||
|
|
@ -120,10 +123,12 @@ private fun WheelCompleteContent(
|
|||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = "✓",
|
||||
fontSize = 64.sp,
|
||||
color = Color(0xFFB98AF4)
|
||||
StatusGlyph(
|
||||
icon = Icons.Filled.Check,
|
||||
tint = CloserPalette.PurpleDeep,
|
||||
container = CloserPalette.PurpleMist,
|
||||
size = 82.dp,
|
||||
iconSize = 40.dp
|
||||
)
|
||||
|
||||
Column(
|
||||
|
|
|
|||
Loading…
Reference in New Issue