P0.2: migrate screens to LocalDataManager.current
Swaps direct `DataManager.xxx` access for `LocalDataManager.current.xxx` across every Compose screen under ui/screens/** that references the singleton. Each composable resolves the ambient once at the top of its body and reuses the local val for subsequent reads — keeping rewrites minimal and predictable. Screens touched: - HomeScreen (totalSummary) - ResidencesScreen (totalSummary) - ResidenceDetailScreen (currentUser) - ResidenceFormScreen (currentUser) - ProfileScreen (currentUser + subscription) - ContractorDetailScreen (residences) - subscription/FeatureComparisonScreen (featureBenefits) - onboarding/OnboardingFirstTaskContent (residences × 3 sites) No behavior change — in production the ambient default resolves to the same DataManager singleton. The change is purely so tests, previews, and the parity-gallery can `CompositionLocalProvider(LocalDataManager provides fake)` to substitute a fake without tearing screens apart. Files under ui/subscription/** and ui/components/AddTaskDialog.kt also reference DataManager but live outside ui/screens/** (plan's scope) — flagged for a follow-up pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.ui.components.AddContractorDialog
|
||||
import com.tt.honeyDue.ui.components.ApiResultHandler
|
||||
import com.tt.honeyDue.ui.components.HandleErrors
|
||||
@@ -42,6 +42,7 @@ fun ContractorDetailScreen(
|
||||
onNavigateBack: () -> Unit,
|
||||
viewModel: ContractorViewModel = viewModel { ContractorViewModel() }
|
||||
) {
|
||||
val dataManager = LocalDataManager.current
|
||||
val contractorState by viewModel.contractorDetailState.collectAsStateWithLifecycle()
|
||||
val deleteState by viewModel.deleteState.collectAsStateWithLifecycle()
|
||||
val toggleFavoriteState by viewModel.toggleFavoriteState.collectAsStateWithLifecycle()
|
||||
@@ -146,7 +147,7 @@ fun ContractorDetailScreen(
|
||||
.testTag(AccessibilityIds.Contractor.detailView)
|
||||
) {
|
||||
val uriHandler = LocalUriHandler.current
|
||||
val residences = DataManager.residences.value
|
||||
val residences = dataManager.residences.value
|
||||
|
||||
ApiResultHandler(
|
||||
state = contractorState,
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.tt.honeyDue.ui.theme.*
|
||||
import com.tt.honeyDue.viewmodel.ResidenceViewModel
|
||||
import com.tt.honeyDue.viewmodel.TaskViewModel
|
||||
import com.tt.honeyDue.network.ApiResult
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import honeydue.composeapp.generated.resources.*
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@@ -33,8 +33,9 @@ fun HomeScreen(
|
||||
viewModel: ResidenceViewModel = viewModel { ResidenceViewModel() },
|
||||
taskViewModel: TaskViewModel = viewModel { TaskViewModel() }
|
||||
) {
|
||||
val dataManager = LocalDataManager.current
|
||||
val summaryState by viewModel.myResidencesState.collectAsStateWithLifecycle()
|
||||
val totalSummary by DataManager.totalSummary.collectAsStateWithLifecycle()
|
||||
val totalSummary by dataManager.totalSummary.collectAsStateWithLifecycle()
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.tt.honeyDue.ui.theme.*
|
||||
import com.tt.honeyDue.viewmodel.AuthViewModel
|
||||
import com.tt.honeyDue.network.ApiResult
|
||||
import com.tt.honeyDue.network.APILayer
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.ui.subscription.UpgradePromptDialog
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
@@ -68,8 +68,9 @@ fun ProfileScreen(
|
||||
val updateState by viewModel.updateProfileState.collectAsStateWithLifecycle()
|
||||
val deleteAccountState by viewModel.deleteAccountState.collectAsStateWithLifecycle()
|
||||
val currentTheme by remember { derivedStateOf { ThemeManager.currentTheme } }
|
||||
val currentSubscription by DataManager.subscription.collectAsStateWithLifecycle()
|
||||
val currentUser by DataManager.currentUser.collectAsStateWithLifecycle()
|
||||
val dataManager = LocalDataManager.current
|
||||
val currentSubscription by dataManager.subscription.collectAsStateWithLifecycle()
|
||||
val currentUser by dataManager.currentUser.collectAsStateWithLifecycle()
|
||||
|
||||
// Handle errors for profile update
|
||||
updateState.HandleErrors(
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.tt.honeyDue.models.ContractorSummary
|
||||
import com.tt.honeyDue.network.ApiResult
|
||||
import com.tt.honeyDue.utils.SubscriptionHelper
|
||||
import com.tt.honeyDue.ui.subscription.UpgradePromptDialog
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.util.DateUtils
|
||||
import com.tt.honeyDue.platform.rememberShareResidence
|
||||
import com.tt.honeyDue.analytics.PostHogAnalytics
|
||||
@@ -88,7 +88,8 @@ fun ResidenceDetailScreen(
|
||||
var upgradeTriggerKey by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
// Get current user for ownership checks
|
||||
val currentUser by DataManager.currentUser.collectAsStateWithLifecycle()
|
||||
val dataManager = LocalDataManager.current
|
||||
val currentUser by dataManager.currentUser.collectAsStateWithLifecycle()
|
||||
|
||||
// Residence sharing state and function
|
||||
val (shareState, shareResidence) = rememberShareResidence()
|
||||
|
||||
@@ -21,7 +21,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.testing.AccessibilityIds
|
||||
import com.tt.honeyDue.viewmodel.ResidenceViewModel
|
||||
import com.tt.honeyDue.repository.LookupsRepository
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.models.Residence
|
||||
import com.tt.honeyDue.models.ResidenceCreateRequest
|
||||
import com.tt.honeyDue.models.ResidenceType
|
||||
@@ -68,8 +68,9 @@ fun ResidenceFormScreen(
|
||||
} else {
|
||||
viewModel.createResidenceState.collectAsStateWithLifecycle()
|
||||
}
|
||||
val dataManager = LocalDataManager.current
|
||||
val propertyTypes by LookupsRepository.residenceTypes.collectAsStateWithLifecycle()
|
||||
val currentUser by DataManager.currentUser.collectAsStateWithLifecycle()
|
||||
val currentUser by dataManager.currentUser.collectAsStateWithLifecycle()
|
||||
|
||||
// Check if current user is the owner
|
||||
val isCurrentUserOwner = remember(existingResidence, currentUser) {
|
||||
|
||||
@@ -41,7 +41,7 @@ import com.tt.honeyDue.utils.SubscriptionHelper
|
||||
import com.tt.honeyDue.ui.subscription.UpgradePromptDialog
|
||||
import com.tt.honeyDue.analytics.PostHogAnalytics
|
||||
import com.tt.honeyDue.analytics.AnalyticsEvents
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.ui.theme.*
|
||||
import honeydue.composeapp.generated.resources.*
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
@@ -61,8 +61,9 @@ fun ResidencesScreen(
|
||||
viewModel: ResidenceViewModel = viewModel { ResidenceViewModel() },
|
||||
taskViewModel: TaskViewModel = viewModel { TaskViewModel() }
|
||||
) {
|
||||
val dataManager = LocalDataManager.current
|
||||
val myResidencesState by viewModel.myResidencesState.collectAsStateWithLifecycle()
|
||||
val totalSummary by DataManager.totalSummary.collectAsStateWithLifecycle()
|
||||
val totalSummary by dataManager.totalSummary.collectAsStateWithLifecycle()
|
||||
var isRefreshing by remember { mutableStateOf(false) }
|
||||
var showUpgradePrompt by remember { mutableStateOf(false) }
|
||||
var upgradeTriggerKey by remember { mutableStateOf<String?>(null) }
|
||||
|
||||
@@ -24,7 +24,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.analytics.AnalyticsEvents
|
||||
import com.tt.honeyDue.analytics.PostHogAnalytics
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.models.TaskCreateRequest
|
||||
import com.tt.honeyDue.models.TaskSuggestionResponse
|
||||
import com.tt.honeyDue.models.TaskSuggestionsResponse
|
||||
@@ -66,6 +66,7 @@ fun OnboardingFirstTaskContent(
|
||||
viewModel: OnboardingViewModel,
|
||||
onTasksAdded: () -> Unit
|
||||
) {
|
||||
val dataManager = LocalDataManager.current
|
||||
var selectedBrowseIds by remember { mutableStateOf(setOf<Int>()) }
|
||||
var selectedSuggestionIds by remember { mutableStateOf(setOf<Int>()) }
|
||||
var expandedCategoryId by remember { mutableStateOf<Int?>(null) }
|
||||
@@ -79,7 +80,7 @@ fun OnboardingFirstTaskContent(
|
||||
// Kick off both network calls on mount. Suggestions needs a residence;
|
||||
// the grouped catalog is user-independent and safe to load immediately.
|
||||
LaunchedEffect(Unit) {
|
||||
val residence = DataManager.residences.value.firstOrNull()
|
||||
val residence = dataManager.residences.value.firstOrNull()
|
||||
if (residence != null) {
|
||||
viewModel.loadSuggestions(residence.id)
|
||||
}
|
||||
@@ -256,7 +257,7 @@ fun OnboardingFirstTaskContent(
|
||||
}
|
||||
|
||||
// Tab content
|
||||
val residenceForRetry = DataManager.residences.value.firstOrNull()
|
||||
val residenceForRetry = dataManager.residences.value.firstOrNull()
|
||||
if (selectedTabIndex == 0 && showTabs) {
|
||||
ForYouTabContent(
|
||||
suggestionsState = suggestionsState,
|
||||
@@ -328,7 +329,7 @@ fun OnboardingFirstTaskContent(
|
||||
if (selectedBrowseIds.isEmpty() && selectedSuggestionIds.isEmpty()) {
|
||||
skipOnboarding("user_skip")
|
||||
} else {
|
||||
val residence = DataManager.residences.value.firstOrNull()
|
||||
val residence = dataManager.residences.value.firstOrNull()
|
||||
if (residence != null) {
|
||||
val today = DateUtils.getTodayString()
|
||||
val taskRequests = mutableListOf<TaskCreateRequest>()
|
||||
|
||||
@@ -40,7 +40,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tt.honeyDue.analytics.AnalyticsEvents
|
||||
import com.tt.honeyDue.analytics.PostHogAnalytics
|
||||
import com.tt.honeyDue.data.DataManager
|
||||
import com.tt.honeyDue.data.LocalDataManager
|
||||
import com.tt.honeyDue.models.FeatureBenefit
|
||||
import com.tt.honeyDue.ui.components.common.StandardCard
|
||||
import com.tt.honeyDue.ui.theme.AppSpacing
|
||||
@@ -56,7 +56,9 @@ import com.tt.honeyDue.ui.theme.AppSpacing
|
||||
* - Header ("Choose Your Plan" + subtitle)
|
||||
* - Two-column comparison table rendered inside a [StandardCard]
|
||||
* (Feature | Free | Pro) with N rows sourced from
|
||||
* `DataManager.featureBenefits`, falling back to a 4-row default list.
|
||||
* `LocalDataManager.current.featureBenefits` (resolves to the
|
||||
* `DataManager` singleton in production), falling back to a 4-row
|
||||
* default list.
|
||||
* - CTA button at the bottom ("Upgrade to Pro") which fires analytics
|
||||
* event [AnalyticsEvents.PAYWALL_COMPARE_CTA] and invokes
|
||||
* [onNavigateToUpgrade].
|
||||
@@ -71,7 +73,8 @@ fun FeatureComparisonScreen(
|
||||
onNavigateBack: () -> Unit,
|
||||
onNavigateToUpgrade: () -> Unit,
|
||||
) {
|
||||
val benefits by DataManager.featureBenefits.collectAsStateWithLifecycle()
|
||||
val dataManager = LocalDataManager.current
|
||||
val benefits by dataManager.featureBenefits.collectAsStateWithLifecycle()
|
||||
val rows = FeatureComparisonScreenState.resolveFeatureRows(benefits)
|
||||
|
||||
Scaffold(
|
||||
|
||||
Reference in New Issue
Block a user