The Today Summary module serves as the application’s “Home” screen. It is designed to provide immediate feedback on a user’s phone usage through a high-level dashboard. It aggregates complex data points—such as , scroll distance, and notification counts—into a cohesive, actionable interface.The module’s primary goal is to facilitate “mindful scrolling” by surfacing and providing quick access to app-specific limits.
This feature follows a strict architecture. The AppScaffold acts as the global container, while the MainScreen serves as the primary entry point for the dashboard logic.
When the screen loads, the TodaySummaryViewModel triggers a data refresh. Because the app relies on sensitive Android permissions (Accessibility, Usage Stats), the module includes a PermissionsCard. This component dynamically appears if the detects missing requirements, ensuring the data shown is accurate.
The module uses a Global Snackbar Architecture. Instead of every screen managing its own snackbar logic, they use a LocalSnackbarHostState provided via . This ensures that snackbars are positioned correctly above the navigation bar and don’t overlap with critical UI elements.
The dashboard doesn’t just display raw numbers; it performs significant data manipulation:
Aggregation: Usage records from the DailyAppUsageRecord table are grouped by package name and summed to provide total daily totals.
Comparison Logic: The system compares today’s metrics against yesterday’s (e.g., “15% less than yesterday”) using a StatComparison utility.
Unit Conversion: Raw scroll pixels are converted into human-readable meters or kilometers via the ConversionUtil.
Heuristics: The AppMetadataRepository uses heuristics (like checking for a launcher intent) to filter out system processes and only show “User-Visible” apps.
Hilt: Used for of repositories into the ViewModel.
Lottie: Powers the “Fitness-style” pull-to-refresh animations.
Jetpack Navigation: Manages transitions between the Dashboard, App Details, and Limit Configuration screens.
HapticsManager: Provides tactile feedback during “Coach Suggestion” swipes and refresh triggers.
Copy
// Example of the complex state combination in the ViewModelval todaySummaryUiState: StateFlow<TodaySummaryUiState> = todayDataFlow.map { data -> TodaySummaryUiState( totalUsageTimeFormatted = dateUtil.formatDurationCompactSymbols(data.summary?.totalUsageTimeMillis ?: 0L), todaysAppUsageUiList = appUiModelMapper.mapToAppUsageUiItems(data.dailyAppUsage), scrollComparison = calculateComparison(data.currentScroll, data.yesterdayScroll), // ... other mappings )}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L), InitialState)