MonoMail is divided into 13 modules:
:app # Main application shell (DI, NavGraph, ActionQueueManager)
:core:model # Pure domain models
:core:designsystem # Theme, typography, shared UI components
:core:database # Room database, entities, DAOs, migrations
:core:network # Retrofit APIs, Gmail/Outlook/IMAP providers
:core:data # Repository, auth, settings, workers
:core:pgp # PGP encryption engine
:feature:auth # Sign-in screens and ViewModels
:feature:inbox # Inbox, dock bar, email list
:feature:detail # Email thread detail screen
:feature:compose # Email compose screen
:feature:settings # Settings hub and 11 sub-screens
:feature:attachment # In-app attachment viewer UI (Compose) -> ViewModel -> EmailRepository -> Room DB (local cache)
-> EmailProvider (Gmail/Outlook/IMAP API)
Writes: UI -> ViewModel -> EmailRepository
-> update Room DB immediately (optimistic)
-> insert PendingActionEntity
-> ActionQueueManager processes pending actions against provider API The app prioritises the local database:
EmailRepository.refreshInbox() fetches from provider and upserts into Room.| Layer | Mechanism |
|---|---|
| Local database | SQLCipher encryption (256-bit key, stored in EncryptedSharedPreferences) |
| Account credentials | AES-GCM via Android KeyStore |
| IMAP passwords | AES-GCM encrypted strings |
| PGP private keys | Armored file encrypted via SecurityUtil |
| PGP passphrases | Encrypted blobs on disk |
| DataStore | EncryptedSharedPreferences (AES256_GCM value encryption, AES256_SIV key encryption) |
| Network | Retrofit with Bearer token auth, 401 detection for re-auth |
MonoMail uses spring physics throughout for tactile feedback. No easing curves — everything bounces naturally.
| Element | Animation | Spec |
|---|---|---|
| Settings card press | Scale to 0.97 | Spring.DampingRatioMediumBouncy restore |
| Theme selector tap | Selected segment bounces to 1.04x | Spring.DampingRatioMediumBouncy + colour tween (250ms) |
| Dock tab switch | Animated background, icon tint, label width | updateTransition |
| Sent overlay | Spring scale-in + fade-in | dampingRatio 0.5, stiffness 300 |
| Loading shimmer | Sweeping linear gradient | Infinite tween(1000ms) |
| Conversations expand/collapse | Content size animation | Spring |