Architecture overview
From src/main.rs:62:- Immediate-mode: UI rebuilt every frame based on current state
- Single state struct: All application state in
Hootstruct - No retained widgets: Widget state ephemeral, recreated each frame
- Fast iteration: UI code reads like drawing commands
Page system
Navigation uses an enum to represent different views:- Has dedicated module in
src/ui/ - Implements its own rendering logic
- Shares common state from
Hootstruct - Can modify app state during render
Component modules
From src/ui/mod.rs:- Page-specific rendering code
- User interaction handling
- State management for that view
- Database queries and updates
ComposeWindow
Floating window for composing messages:- Multiple instances: Can have multiple compose windows open simultaneously
- Unique IDs: Each window tracked by
egui::Id(random u32) - Draft support: Auto-save to drafts, restore from drafts
- Account selector: Choose sending identity and NIP-05
- NIP-05 resolution: Resolve recipient addresses in real-time
- Rich editor: Toolbar for formatting (future implementation)
ContactsManager
Manages contact list with metadata and images:- Petnames: Optional user-assigned names for contacts
- Metadata caching: Profile info cached for performance
- Image loading: Background thread loading of profile images
- Sorted display: Contacts sorted alphabetically by best name
- Add/remove: CRUD operations synced with database
Image loading
Profile images loaded asynchronously:- UI requests image for pubkey
- If not cached, spawn background thread
- Thread downloads image via HTTP
- Image decoded and uploaded to GPU
TextureHandlecached for subsequent frames- UI displays image or fallback initials
Layout structure
Main application layout:- Left panel: Navigation and compose button (fixed width)
- Central panel: Main content area (fills remaining space)
- Right panel: Optional detail view (conditional)
State management
Application state organization:- Centralized: All state in
Hootstruct - Mutable: Components receive
&mut Hootfor modification - Persistent: State survives across frames
- Serializable: Some state persisted to disk (via eframe)
Event loop
Main update/render loop:- Process network events (relay messages)
- Update connection state (keepalive)
- Render main UI (navigation + content)
- Render floating windows (compose windows)
- Clean up closed windows
Styling
Custom theme and colors:Performance considerations
- Retained mode where needed: Window state, images, metadata cached
- Lazy loading: Profile metadata fetched on-demand
- Background threads: Network operations off main thread
- Efficient repaints: Only repaint when events occur (wake-up callbacks)
- Virtual scrolling: Large lists use
egui::ScrollArea