refactor(cleanup): dead code + hygiene batch from games review
- Delete unused ui/theme/Color.kt (zero refs; live palette is Theme.kt).
- Remove orphaned EditProfileScreen wrapper composable (no route references it;
AccountScreen embeds EditProfileContent, which stays).
- Debug-gate ArtPreviewScreen + PairedHomePreviewScreen out of the release nav
graph (BuildConfig.DEBUG).
- Collapse duplicate wheel_history route into game_history (same screen; wheel
surfaces now navigate to Past Games directly).
- CouplePremiumChecker: inject AuthRepository instead of raw
FirebaseAuth.getInstance() (finishes the in-flight auth-DI refactor for
non-data-layer call sites).
- Copy/UI polish: 'It's a match!' (matches the push copy), internal 'mc' token
never renders in the Home daily pill ('Daily Fun Mc' → 'Daily Fun'),
welcome/splash privacy tagline no longer clips mid-sentence (maxLines 4 +
ellipsis, AUTH-TRUNC-001).
Unit + functions suites green; assembleDebug clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e5868bd6b1
commit
c36a101d38
|
|
@ -2,7 +2,7 @@ package app.closer.core.billing
|
||||||
|
|
||||||
import app.closer.data.remote.FirestoreCollections
|
import app.closer.data.remote.FirestoreCollections
|
||||||
import app.closer.domain.repository.CoupleRepository
|
import app.closer.domain.repository.CoupleRepository
|
||||||
import com.google.firebase.auth.FirebaseAuth
|
import app.closer.domain.repository.AuthRepository
|
||||||
import com.google.firebase.firestore.FirebaseFirestore
|
import com.google.firebase.firestore.FirebaseFirestore
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -29,11 +29,12 @@ import javax.inject.Singleton
|
||||||
class CouplePremiumChecker @Inject constructor(
|
class CouplePremiumChecker @Inject constructor(
|
||||||
private val entitlementChecker: EntitlementChecker,
|
private val entitlementChecker: EntitlementChecker,
|
||||||
private val firestore: FirebaseFirestore,
|
private val firestore: FirebaseFirestore,
|
||||||
private val coupleRepository: CoupleRepository
|
private val coupleRepository: CoupleRepository,
|
||||||
|
private val authRepository: AuthRepository
|
||||||
) {
|
) {
|
||||||
/** Couple-shared premium for the current user (resolves the partner internally). Drop-in for EntitlementChecker. */
|
/** Couple-shared premium for the current user (resolves the partner internally). Drop-in for EntitlementChecker. */
|
||||||
fun isPremium(): Flow<Boolean> = flow {
|
fun isPremium(): Flow<Boolean> = flow {
|
||||||
val uid = FirebaseAuth.getInstance().currentUser?.uid
|
val uid = authRepository.currentUserId
|
||||||
val partnerId = uid?.let {
|
val partnerId = uid?.let {
|
||||||
runCatching { coupleRepository.getCoupleForUser(it)?.userIds?.firstOrNull { id -> id != it } }.getOrNull()
|
runCatching { coupleRepository.getCoupleForUser(it)?.userIds?.firstOrNull { id -> id != it } }.getOrNull()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -477,9 +477,6 @@ fun AppNavigation(
|
||||||
onNavigate = navigateRoute
|
onNavigate = navigateRoute
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
composable(route = AppRoute.WHEEL_HISTORY) {
|
|
||||||
GameHistoryScreen(onNavigate = navigateRoute)
|
|
||||||
}
|
|
||||||
composable(route = AppRoute.GAME_HISTORY) {
|
composable(route = AppRoute.GAME_HISTORY) {
|
||||||
GameHistoryScreen(onNavigate = navigateRoute)
|
GameHistoryScreen(onNavigate = navigateRoute)
|
||||||
}
|
}
|
||||||
|
|
@ -604,11 +601,14 @@ fun AppNavigation(
|
||||||
composable(route = AppRoute.ACTIVITY) {
|
composable(route = AppRoute.ACTIVITY) {
|
||||||
ActivityScreen(onNavigate = navigateRoute)
|
ActivityScreen(onNavigate = navigateRoute)
|
||||||
}
|
}
|
||||||
composable(route = AppRoute.ART_PREVIEW) {
|
// Dev-only art/layout previews: keep them out of the release nav graph.
|
||||||
app.closer.ui.debug.ArtPreviewScreen(onNavigate = navigateRoute)
|
if (app.closer.BuildConfig.DEBUG) {
|
||||||
}
|
composable(route = AppRoute.ART_PREVIEW) {
|
||||||
composable(route = AppRoute.PAIRED_HOME_PREVIEW) {
|
app.closer.ui.debug.ArtPreviewScreen(onNavigate = navigateRoute)
|
||||||
app.closer.ui.home.PairedHomePreviewScreen(onNavigate = navigateRoute)
|
}
|
||||||
|
composable(route = AppRoute.PAIRED_HOME_PREVIEW) {
|
||||||
|
app.closer.ui.home.PairedHomePreviewScreen(onNavigate = navigateRoute)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ object AppRoute {
|
||||||
const val DELETE_ACCOUNT = "delete_account"
|
const val DELETE_ACCOUNT = "delete_account"
|
||||||
const val SECURITY = "security_settings"
|
const val SECURITY = "security_settings"
|
||||||
const val CHANGE_PASSWORD = "change_password"
|
const val CHANGE_PASSWORD = "change_password"
|
||||||
const val WHEEL_HISTORY = "wheel_history"
|
|
||||||
const val GAME_HISTORY = "game_history"
|
const val GAME_HISTORY = "game_history"
|
||||||
const val THIS_OR_THAT_REPLAY = "this_or_that_replay/{sessionId}"
|
const val THIS_OR_THAT_REPLAY = "this_or_that_replay/{sessionId}"
|
||||||
const val DESIRE_SYNC_REPLAY = "desire_sync_replay/{sessionId}"
|
const val DESIRE_SYNC_REPLAY = "desire_sync_replay/{sessionId}"
|
||||||
|
|
@ -122,7 +121,6 @@ object AppRoute {
|
||||||
Definition(DELETE_ACCOUNT, "Delete Account", "settings"),
|
Definition(DELETE_ACCOUNT, "Delete Account", "settings"),
|
||||||
Definition(SECURITY, "Security", "settings"),
|
Definition(SECURITY, "Security", "settings"),
|
||||||
Definition(CHANGE_PASSWORD, "Change Password", "settings"),
|
Definition(CHANGE_PASSWORD, "Change Password", "settings"),
|
||||||
Definition(WHEEL_HISTORY, "Wheel History", "wheel"),
|
|
||||||
Definition(GAME_HISTORY, "Past Games", "play"),
|
Definition(GAME_HISTORY, "Past Games", "play"),
|
||||||
Definition(THIS_OR_THAT_REPLAY, "This or That Results", "play"),
|
Definition(THIS_OR_THAT_REPLAY, "This or That Results", "play"),
|
||||||
Definition(DESIRE_SYNC_REPLAY, "Desire Sync Results", "play"),
|
Definition(DESIRE_SYNC_REPLAY, "Desire Sync Results", "play"),
|
||||||
|
|
@ -178,7 +176,6 @@ object AppRoute {
|
||||||
SPIN_WHEEL_RANDOM,
|
SPIN_WHEEL_RANDOM,
|
||||||
WHEEL_SESSION,
|
WHEEL_SESSION,
|
||||||
WHEEL_COMPLETE,
|
WHEEL_COMPLETE,
|
||||||
WHEEL_HISTORY,
|
|
||||||
GAME_HISTORY,
|
GAME_HISTORY,
|
||||||
THIS_OR_THAT_REPLAY,
|
THIS_OR_THAT_REPLAY,
|
||||||
DESIRE_SYNC_REPLAY,
|
DESIRE_SYNC_REPLAY,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
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.dp
|
||||||
import app.closer.ui.brand.CloserBrandCopy
|
import app.closer.ui.brand.CloserBrandCopy
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -79,7 +80,10 @@ fun BrandMessageRotator(
|
||||||
style = style,
|
style = style,
|
||||||
color = color,
|
color = color,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
maxLines = 3
|
// The primary privacy message wraps to 4 lines at default font scale on the
|
||||||
|
// welcome/splash width; 3 clipped it mid-sentence with no ellipsis (AUTH-TRUNC-001).
|
||||||
|
maxLines = 4,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -585,7 +585,7 @@ private fun MatchOverlay(
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "It is a match!",
|
text = "It’s a match!",
|
||||||
style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.SemiBold),
|
style = MaterialTheme.typography.headlineSmall.copy(fontWeight = FontWeight.SemiBold),
|
||||||
color = MaterialTheme.colorScheme.onSurface
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1015,6 +1015,8 @@ class HomeViewModel @Inject constructor(
|
||||||
private fun String.toHomeLabel(): String =
|
private fun String.toHomeLabel(): String =
|
||||||
split("_", "-")
|
split("_", "-")
|
||||||
.filter { part -> part.isNotBlank() }
|
.filter { part -> part.isNotBlank() }
|
||||||
|
// Internal format tokens (e.g. the "mc" in daily_fun_mc) must never face users.
|
||||||
|
.filterNot { part -> part.lowercase() in setOf("mc") }
|
||||||
.joinToString(" ") { part -> part.replaceFirstChar { it.uppercaseChar() } }
|
.joinToString(" ") { part -> part.replaceFirstChar { it.uppercaseChar() } }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -76,44 +76,8 @@ import app.closer.ui.settings.SettingsPrimaryDeep
|
||||||
import app.closer.ui.components.CloserGlyphs
|
import app.closer.ui.components.CloserGlyphs
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
// The routed EditProfileScreen wrapper was removed as dead code (no nav route references
|
||||||
fun EditProfileScreen(
|
// it); AccountScreen embeds EditProfileContent directly.
|
||||||
onNavigate: (String) -> Unit = {},
|
|
||||||
viewModel: EditProfileViewModel = hiltViewModel()
|
|
||||||
) {
|
|
||||||
val snackbar = remember { SnackbarHostState() }
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
snackbarHost = { SnackbarHost(snackbar) },
|
|
||||||
containerColor = Color.Transparent,
|
|
||||||
modifier = Modifier.background(SettingsBackgroundBrush),
|
|
||||||
topBar = {
|
|
||||||
TopAppBar(
|
|
||||||
title = { Text("Edit profile", color = SettingsInk) },
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = { onNavigate("back") }) {
|
|
||||||
Icon(
|
|
||||||
CloserGlyphs.Back,
|
|
||||||
contentDescription = "Back",
|
|
||||||
tint = SettingsInk
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) { padding ->
|
|
||||||
EditProfileContent(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(padding)
|
|
||||||
.verticalScroll(rememberScrollState()),
|
|
||||||
snackbar = snackbar,
|
|
||||||
viewModel = viewModel
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EditProfileContent(
|
fun EditProfileContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
package app.closer.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
|
|
||||||
// Dark theme colors (for reference if needed)
|
|
||||||
val darkPrimaryColor = Color(0xFFD7BBFF)
|
|
||||||
val darkPrimaryContainerColor = Color(0xFF4D3865)
|
|
||||||
val darkSecondaryColor = Color(0xFFE8B7D0)
|
|
||||||
val darkTertiaryColor = Color(0xFFC9C1FF)
|
|
||||||
val darkBackgroundColor = Color(0xFF111015)
|
|
||||||
val darkSurfaceColor = Color(0xFF19161F)
|
|
||||||
val darkErrorColor = Color(0xFFFFB4AB)
|
|
||||||
|
|
||||||
val darkOnPrimaryColor = Color(0xFF37204E)
|
|
||||||
val darkOnPrimaryContainerColor = Color(0xFFF2E8FF)
|
|
||||||
val darkOnSecondaryColor = Color(0xFF482638)
|
|
||||||
val darkOnTertiaryColor = Color(0xFF302A55)
|
|
||||||
val darkOnBackgroundColor = Color(0xFFEDE7EF)
|
|
||||||
val darkOnSurfaceColor = Color(0xFFEDE7EF)
|
|
||||||
val darkOnErrorColor = Color(0xFF690005)
|
|
||||||
|
|
@ -63,7 +63,7 @@ fun CategoryPickerScreen(
|
||||||
if (item.isLocked) onNavigate(AppRoute.PAYWALL)
|
if (item.isLocked) onNavigate(AppRoute.PAYWALL)
|
||||||
else onNavigate(AppRoute.spinWheel(item.category.id))
|
else onNavigate(AppRoute.spinWheel(item.category.id))
|
||||||
},
|
},
|
||||||
onHistory = { onNavigate(AppRoute.WHEEL_HISTORY) },
|
onHistory = { onNavigate(AppRoute.GAME_HISTORY) },
|
||||||
onRetry = viewModel::load
|
onRetry = viewModel::load
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ class SpinWheelViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onHistory() {
|
fun onHistory() {
|
||||||
_uiState.update { it.copy(navigateTo = AppRoute.WHEEL_HISTORY) }
|
_uiState.update { it.copy(navigateTo = AppRoute.GAME_HISTORY) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onNavigated() {
|
fun onNavigated() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue