Skip to main content

Overview

The Notification Insights module serves as a dual-purpose feature within the ecosystem. It functions as both a diagnostic tool—providing users with a of their most distracting apps—and an intervention tool via the Post Box (Notification Batching). To the user, this feature provides a “Hero” dashboard of today’s notification counts compared to yesterday, a breakdown of which apps are “noisy,” and a control center to intercept notifications from specific apps, delivering them only at scheduled intervals.

Architecture & Data Flow

This module follows a strict pattern, leveraging for dependency orchestration.

The State Pipeline

The NotificationInsightsViewModel acts as a central aggregator. It doesn’t just pass data; it synthesizes it:
  1. Reactive Merging: It uses combine to merge raw package names from SettingsRepository with rich metadata (icons, names) from AppMetadataRepository.
  2. Temporal Filtering: It uses flatMapLatest to switch data streams whenever the user selects a different date on the calendar.
  3. Comparison Logic: It calculates percentage changes between “Today” and “Yesterday” to provide immediate context on whether the user’s digital hygiene is improving.

Key Components

ComponentResponsibility
NotificationInsightsViewModelOrchestrates UI state, handles batching logic, and transforms raw DB counts into displayable models.
NotificationBatchSchedulerManages the logic to trigger notification delivery at user-defined times.
AppMetadataRepositoryThe source of truth for app icons and names, ensuring the UI shows “WhatsApp” instead of com.whatsapp.
SettingsRepositoryPersists user preferences for batching times and selected “distracting” apps using .
CategoryUtilA utility that normalizes raw system categories (e.g., GAME_ACTION) into user-friendly labels (e.g., Games).

Operational Logic

1. Notification Batching (The Post Box)

The “Post Box” is the module’s primary intervention.
  • Selection: Users select specific apps to “batch.”
  • Scheduling: The NotificationBatchScheduler calculates the delay until the next scheduled window (e.g., 09:00, 12:00) and enqueues a OneTimeWorkRequest.
  • Execution: When the timer hits, the system “releases” the intercepted notifications.

2. State Management & Initialization

When the screen loads, the module performs a multi-stage initialization:
  • Loading State: A _isLoading is set to true while the ScrollDataRepository fetches historical summaries.
  • Heatmap Generation: The heatmapData stream parses historical notification records into a Map<LocalDate, Int> to power the calendar visualization.

3. Edge Cases & Resilience

  • Empty States: If no notifications are recorded (e.g., a new install), the EmptyStateCard is displayed to guide the user.
  • Time Sanitization: The SettingsRepository enforces a maximum of 5 batching slots and ensures time strings are correctly formatted as HH:mm.
  • App Uninstalls: The AppMetadataRepository handles the handleAppUninstalled event, ensuring the UI doesn’t crash if a batched app is removed from the device.

Data Engineering & Transformation

The module performs significant data manipulation to ensure performance and clarity:
  • Source Tables: Data is primarily derived from NotificationRecord (for counts) and AppMetadata (for UI context).
  • The “Other” Logic: In the Treemap visualization, the ViewModel calculates a “remainder” fraction. If small apps contribute less than 5% of total noise, they are bundled into an “Other” category to prevent UI clutter.
  • Asynchronous Mapping: App icons are stored as local files. The ViewModel maps package names to iconFilePath strings, which are then loaded asynchronously by the UI using the library.
  • Thread Safety: All repository interactions are wrapped in , ensuring that heavy database queries for 7-day averages don’t cause UI jank.

Dependencies

  • WorkManager: For reliable background scheduling of notification releases.
  • Material 3: For the TimePicker and BottomSheet components.
  • Timber: Used for internal logging of metadata sync events.
  • Dagger Hilt: For providing singleton instances of repositories to the ViewModel.
Last modified on January 22, 2026