Skip to main content

Overview

The Detail module is the analytical heart of the application. It serves two primary purposes:
  1. Scroll Dashboard: A high-level overview of scrolling behavior across all apps, featuring a and ranked lists.
  2. App Deep-Dive: A granular view of a specific application’s performance, including “Focus Quality” (active vs. passive time), “Physical Effort” (meters scrolled), and “Launch Triggers” (notifications vs. intentional opens).
This module transforms raw system events into human-readable “physical” metrics, helping users understand the literal distance their thumbs travel.

Architecture & Data Flow

The module follows a strict architecture. It leverages a “Mapper” pattern to decouple the database entities from the UI requirements.

Data Pipeline

  1. Extraction: ViewModels request data from ScrollDataRepository and AppMetadataRepository based on a selected LocalDate or ScrollDetailPeriod (Daily, Weekly, Monthly).
  2. Transformation: The AppUiModelMapper performs heavy lifting by combining usage records, scroll data, and -injected limit configurations into AppScrollUiItem objects.
  3. Presentation: The UI observes a single UiState (for the dashboard) or multiple specialized flows (for app details) to render charts and Bento-style insight grids.

Key Components

ComponentResponsibility
ScrollDetailViewModelManages the dashboard state, handling date selection and period switching (Daily/Weekly/Monthly).
AppDetailViewModelOrchestrates the deep-dive view for a specific package, including chart navigation and app-launch logic.
AppUiModelMapperA utility that merges raw usage data with app metadata (icons, names) and current limit statuses.
LimitViewModelDelegateEncapsulates shared logic for the “Set Limit” bottom sheet, allowing both the dashboard and detail screens to modify app limits consistently.
UsageRepositoryProvides a “live” view of usage by combining historical DB records with the current active session.

Operational Logic

1. State Management & Reactivity

The ViewModels use flatMapLatest and combine operators to ensure the UI stays in sync with user interactions. For example, when a user changes the date on the heatmap, the ScrollDetailViewModel automatically triggers a new data fetch for that specific window, re-mapping all app items to reflect that day’s usage.

2. The “Removed Apps” Logic

A unique feature of this module is its handling of uninstalled applications. If the ScrollDataRepository returns data for a package that is no longer found in AppMetadataRepository, the system aggregates these into a RemovedAppsData object. This ensures that historical “physical effort” is never lost, even if the app is deleted.

3. Tutorial Integration

The module uses a TutorialScaffold and TutorialRepository to manage the “Spotlight” onboarding. It tracks whether a user has seen the scroll distance explanation and uses TutorialTargetId to highlight specific UI elements like the “Limit Icon” or “Heatmap.”

Data Engineering & Transformation

Physical Metric Calculation

The module relies on a ConversionUtil to translate raw or pixels into meters and kilometers.
  • Legacy Data: Older versions stored scroll data in pixels. The AppDetailViewModel includes logic to normalize legacy pixels to micrometers (using a 160 DPI baseline) to maintain historical continuity.
  • Aggregation: For Weekly/Monthly views, the system calculates a “Daily Average” by dividing the period total by the number of days, providing a normalized view of behavior trends.

Source Tables & Entities

  • daily_app_usage: Provides usageTimeMillis, activeTimeMillis, and appOpenCount.
  • app_scroll_data: Provides the raw distance metrics.
  • app_metadata: Provides the “User Visible” status and cached icon paths.
  • limit_groups: Defines the time constraints applied to apps.

Dependencies

  • Coil: Used for asynchronous loading of app icons from the internal filesystem.
  • Material3 Expressive: Utilized for the “Back Button” shapes and Bento-grid layouts in AppDetailInsightsGrid.
  • Room & Coroutines: All data fetching is offloaded to Dispatchers.IO via to prevent UI jank during heavy mapping operations.
  • Jetpack Navigation: Handles the transition between the dashboard and specific app details via packageName arguments.
Last modified on January 22, 2026