refactor(android): update question flow and navigation patterns (batch 6)
This commit is contained in:
parent
67251537eb
commit
2a5cd28397
|
|
@ -202,7 +202,7 @@ fun AppNavigation(
|
|||
route = AppRoute.DAILY_QUESTION,
|
||||
deepLinks = listOf(navDeepLink { uriPattern = "closer://closer.app/daily_question" })
|
||||
) {
|
||||
DailyQuestionScreen(onNavigate = navigateRoute)
|
||||
DailyQuestionScreen(onNavigate = navigateRoute, onBack = navigateBackOrHome)
|
||||
}
|
||||
composable(route = AppRoute.QUESTION_PACKS) {
|
||||
QuestionPackLibraryScreen(onNavigate = navigateRoute)
|
||||
|
|
|
|||
|
|
@ -11,10 +11,17 @@ import app.closer.domain.model.Question
|
|||
@Composable
|
||||
fun DailyQuestionScreen(
|
||||
onNavigate: (String) -> Unit = {},
|
||||
onBack: () -> Unit = {},
|
||||
viewModel: DailyQuestionViewModel = hiltViewModel()
|
||||
) {
|
||||
val state by viewModel.uiState.collectAsState()
|
||||
|
||||
// Reveal is only offered once both partners have answered — the reveal screen enforces
|
||||
// this too, but surfacing the button early is misleading and should be avoided.
|
||||
val revealRoute: (() -> Unit)? = if (state.submitted && state.partnerHasAnswered) {
|
||||
state.question?.let { q -> { onNavigate(AppRoute.answerReveal(q.id)) } }
|
||||
} else null
|
||||
|
||||
LocalQuestionContent(
|
||||
state = state,
|
||||
title = "One question, enough space",
|
||||
|
|
@ -25,20 +32,17 @@ fun DailyQuestionScreen(
|
|||
if (coupleId != null) {
|
||||
onNavigate(AppRoute.questionThread(coupleId, question.id))
|
||||
} else {
|
||||
// Discussing requires a paired partner; send unpaired users to invite one.
|
||||
onNavigate(AppRoute.CREATE_INVITE)
|
||||
}
|
||||
},
|
||||
onSecondaryRoute = state.question?.let {
|
||||
{ onNavigate(AppRoute.answerReveal(it.id)) }
|
||||
},
|
||||
secondaryRouteLabel = "Reveal",
|
||||
onSecondaryRoute = revealRoute,
|
||||
secondaryRouteLabel = if (revealRoute != null) "Reveal" else null,
|
||||
onWrittenTextChanged = viewModel::updateWrittenText,
|
||||
onOptionToggled = viewModel::toggleOption,
|
||||
onScaleChanged = viewModel::updateScale,
|
||||
onSubmit = viewModel::submitAnswer,
|
||||
canSubmit = viewModel.canSubmit(),
|
||||
onRefresh = viewModel::loadDailyQuestion
|
||||
onBack = onBack
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ data class LocalQuestionUiState(
|
|||
val submitted: Boolean = false,
|
||||
val pendingWrittenText: String = "",
|
||||
val pendingSelectedOptionIds: List<String> = emptyList(),
|
||||
val pendingScaleValue: Int = 3
|
||||
val pendingScaleValue: Int = 3,
|
||||
val partnerHasAnswered: Boolean = false
|
||||
)
|
||||
|
||||
@HiltViewModel
|
||||
|
|
@ -55,12 +56,16 @@ class DailyQuestionViewModel @Inject constructor(
|
|||
val today = FirestoreAnswerDataSource.todayLocalDateString()
|
||||
val (coupleId, question) = loadCoupleAndQuestion(today)
|
||||
val answer = question?.let { localAnswerRepository.getAnswer(it.id) }
|
||||
val partnerHasAnswered = coupleId?.let {
|
||||
runCatching { checkPartnerAnswered(it, today) }.getOrDefault(false)
|
||||
} ?: false
|
||||
_uiState.value = LocalQuestionUiState(
|
||||
isLoading = false,
|
||||
question = question,
|
||||
coupleId = coupleId,
|
||||
dailyQuestionDate = today,
|
||||
pendingScaleValue = defaultScaleValue(question)
|
||||
pendingScaleValue = defaultScaleValue(question),
|
||||
partnerHasAnswered = partnerHasAnswered
|
||||
).withLocalAnswer(answer)
|
||||
} catch (e: Exception) {
|
||||
crashReporter.recordException(e)
|
||||
|
|
@ -189,6 +194,17 @@ class DailyQuestionViewModel @Inject constructor(
|
|||
}.onFailure {
|
||||
crashReporter.recordException(it)
|
||||
}
|
||||
// After submitting, refresh partner-answered status so the reveal button appears
|
||||
// immediately if the partner answered while the user was composing.
|
||||
val partnerHasAnswered = runCatching { checkPartnerAnswered(coupleId, dailyQuestionDate) }.getOrDefault(false)
|
||||
_uiState.update { it.copy(partnerHasAnswered = partnerHasAnswered) }
|
||||
}
|
||||
|
||||
private suspend fun checkPartnerAnswered(coupleId: String, date: String): Boolean {
|
||||
val userId = authRepository.currentUserId ?: return false
|
||||
val couple = runCatching { coupleRepository.getCoupleForUser(userId) }.getOrNull() ?: return false
|
||||
val partnerId = couple.userIds.firstOrNull { it != userId } ?: return false
|
||||
return firestoreAnswerDataSource.getAnswerForUser(coupleId, partnerId, date) != null
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,15 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.foundation.shape.CircleShape
|
||||
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.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.FilledTonalButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Surface
|
||||
|
|
@ -71,6 +75,7 @@ fun LocalQuestionContent(
|
|||
onSubmit: () -> Unit,
|
||||
canSubmit: Boolean,
|
||||
onRefresh: (() -> Unit)? = null,
|
||||
onBack: (() -> Unit)? = null,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val background = closerBackgroundBrush()
|
||||
|
|
@ -89,6 +94,14 @@ fun LocalQuestionContent(
|
|||
.padding(horizontal = 20.dp, vertical = 18.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(18.dp)
|
||||
) {
|
||||
if (onBack != null) {
|
||||
IconButton(onClick = onBack) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
}
|
||||
LocalQuestionHeader(title = title, subtitle = subtitle)
|
||||
|
||||
when {
|
||||
|
|
|
|||
Loading…
Reference in New Issue