Data Schema
Purrsistence uses Room for local data persistence. The schema is designed to support offline-first functionality, with data being synchronized to Supabase when a connection is available and the user is logged in.
Key Entities
1. UserEntity (users)
Stores user profile information and gamification state.
userId: Primary Keyusername: User's display namebalance: Current coin balancefriends: List of friend IDscollectedCatsIds: IDs of cats the user has purchasedselectedCatIds: IDs of cats currently displayed in the room (max 5)isSupabaseLinked: Boolean flag for sync statussupabaseUserId: Remote ID for Supabase mapping
2. GoalEntity (goals)
Represents user-defined focus goals.
id: Primary KeyuserId: Foreign Key toUserEntitytitle: Goal nametype: Category (Weekly, Daily, ..)targetDuration: Desired focus timedeepFocus: Whether app blocking is enabled for this goalisCompleted: Status flaglastCompletedAt: Timestamp of the last completion of set goal
3. TrackingSessionEntity (tracking_sessions)
Logs individual focus sessions.
id: Primary KeygoalId: Foreign Key toGoalEntityuserId: Foreign Key toUserEntitystartTime: Start timestampendTime: End timestampdeepFocus: Whether deep focus was active during the sessionpuaseHistory: Custom string put together to store total pause time, pause intervals and currency earned during the session with multiplier, if paused too longcurrentPauseStart: Timestamp of the start of the current pauselastResetTime: Timestamp of the last time the multiplier was reset
Data Mapping
The application uses different models for different layers to ensure decoupling:
| Layer | Model Type | Example |
|---|---|---|
| Data (Local) | Room Entity | GoalEntity |
| Data (Remote) | Supabase DTO | GoalDto |
| Domain | Kotlin Data Class | Goal |
Converters
Room type converters are used for complex types like Instant, URL, and List<String> (stored as JSON strings in the database). These are defined in com.example.purrsistence.data.local.converter.