Skip to main content

Data Strategy

The application employs a Local-First strategy with asynchronous background synchronization.
  1. Preferences: Managed via , wrapped in reactive .
  2. App Categorization: Uses a State-Machine Sync strategy. Apps are discovered locally, marked as NEEDS_CHECK, and synchronized with a remote service via .
  3. Notifications: Persisted in a database with automated retention policies to prevent storage bloat.

Key Repositories

  • SettingsRepository: The for user preferences (Themes, Dark Mode, Nudge intervals, and the “Pledge”).
  • AppCategoryRepository: Manages the mapping between Android package names and their productivity categories (e.g., “Social”, “Work”).

Schema & Performance (Data Engineering)

App Categorization State Machine

The AppCategory entity tracks the sync status of every installed app:
  • NEEDS_CHECK: Newly discovered app, not yet sent to API.
  • PENDING: API acknowledged the app but is still processing the category (triggers a retry in 15/30 mins).
  • SYNCED: Category successfully retrieved.
  • FAILED: Max retries reached or API error.

Data Integrity

  • User Overrides: If a user manually categorizes an app, the isUserCategorized flag is set to true. The sync engine is hard-coded to never overwrite user-defined data with API results.
  • Batching: API requests are chunked into groups of 100 packages to optimize network overhead and prevent during large initial scans.

Storage & Caching

Data TypeStorage MechanismCaching Policy
User SettingsSharedPreferencesMemory-cached via Flow; persistent across restarts.
App CategoriesRoom DBPermanent local cache; refreshed only if NEEDS_CHECK.
NotificationsRoom DB60-day retention (configurable) managed by NotificationRetentionWorker.

Threading & Concurrency

The module relies heavily on to ensure the UI remains responsive:
  • Reactive Updates: SettingsRepository uses callbackFlow to convert standard listener-based SharedPreferences into streams.
  • Background Execution: All heavy lifting (API calls, DB cleanup) is encapsulated in CoroutineWorker classes.
  • Safe Dispatching: Repository methods are marked as , ensuring they are safe to call from any .

Background Workers

CategorySyncWorker

Triggered either by a full periodic scan or a “Targeted Sync” when a new app is installed. It communicates with the CategoryApiService to fetch metadata.

NotificationRetentionWorker

A periodic worker that runs daily (usually with a 6-hour initial delay). It calculates a “Cutoff Date” and executes a DELETE query on the notifications table to maintain performance.

NotificationBatchWorker (Post Box)

Handles the “Post Box” feature. Instead of showing notifications immediately, it:
  1. Queries the DB for undelivered batched notifications.
  2. Generates a summary notification (e.g., “You have 12 notifications from 4 apps”).
  3. Schedules the next delivery window using NotificationBatchScheduler.
Pro-Tip: The NotificationBatchScheduler uses LocalTime.parse to handle user-defined delivery windows (e.g., “09:00”, “18:00”) and calculates the millisecond delay until the next window accurately, even across day boundaries.
Last modified on January 22, 2026