5.5 KiB
NoteDeck Columns - Developer Guide
This document provides detailed information for developers who want to contribute to or understand the NoteDeck Columns codebase.
Project Structure
The NoteDeck Columns codebase is organized as follows:
notedeck_columns
├── src
│ ├── ui # UI components and views
│ │ ├── note # Note-related UI components (posts, replies, quotes)
│ │ ├── column # Column UI components
│ │ ├── search # Search functionality
│ │ ├── profile # Profile views and editing
│ │ └── ...
│ ├── timeline # Timeline data structures and logic
│ ├── storage # Persistence mechanisms
│ ├── accounts # Account management
│ ├── decks # Deck management
│ ├── app.rs # Main application logic
│ ├── app_creation.rs # Application initialization
│ ├── route.rs # Routing system
│ ├── nav.rs # Navigation logic
│ └── ...
Development Setup
Prerequisites
- Rust toolchain (latest stable recommended)
- nostrdb and its dependencies
- egui and eframe
Building the Project
-
Clone the repository:
git clone https://github.com/damus-io/notedeck cd notedeck -
Build the project:
cargo build --release -
Run the application:
cargo run --release
Development Mode
For development, you might want to run with debug symbols:
cargo run
Core Concepts
Decks and Columns
- Deck: A collection of columns that a user can switch between
- Column: A view into a specific type of Nostr content (timeline, profile, etc.)
Timelines
Timelines are a fundamental concept in NoteDeck Columns:
Timeline: Represents a stream of notes with filters and subscriptionsTimelineKind: Defines the type of timeline (Universe, Profile, Notifications, etc.)TimelineTab: Filtered views of a timeline (e.g., Notes only vs. Notes & Replies)TimelineCache: Caches timeline data for efficient access
Navigation and Routing
Route: Represents application navigation targetsRouter: Manages the navigation stack for each columnNavTitle: Renders the title bar for navigationRenderNavAction: Actions resulting from navigation events
UI Components
The UI is built with egui and organized into components:
PostView,PostReplyView,QuoteRepostView: Note creation UINoteView: Displays Nostr notesProfileView: Displays and edits profilesTimelineView: Renders timelines in columnsDesktopSidePanel: Side navigation panel
Key Implementation Details
Subscriptions and Realtime Updates
NoteDeck Columns manages Nostr subscriptions and relay connections to provide realtime updates:
MultiSubscriber: Handles subscriptions to multiple relaysSubscriptions: Tracks application-wide subscriptionsRelayPool: Manages relay connections
Data Flow
- User actions create routes or trigger navigation
- Routes are mapped to timeline kinds or other UI views
- Timelines query nostrdb for notes matching their filters
- UI components render the note data
- Subscriptions keep the data updated in realtime
State Management
State is managed at different levels:
Damus: Contains global application stateDecksCache: Holds deck and column configurationsTimelineCache: Caches timeline data- Various component-specific state structures
Testing
Run the test suite:
cargo test
The codebase includes unit tests for critical components.
Common Tasks
Adding a New Column Type
- Add a new variant to
TimelineKindenum intimeline/kind.rs - Implement the necessary filter logic
- Update the serialization and parsing methods
- Add UI support in the AddColumn view
Adding UI Components
- Create a new Rust file in the appropriate ui directory
- Implement the component using egui
- Connect it to the routing system if needed
Implementing New Features
When implementing new features:
- Start by understanding the relevant parts of the codebase
- Look for similar implementations as reference
- Follow the existing patterns for state management and UI components
- Add appropriate tests
- Update documentation
Troubleshooting
Common Issues
- Render Issues: Check the egui-related code for layout problems
- Data Freshness: Verify subscription and filter setup
- Performance: Look for inefficient queries or rendering
Debugging
- Use
tracingmacros (debug!,info!,error!) for logging - Run with
RUST_LOG=debugfor verbose output - Use
cargo expandto inspect macro expansion
Architecture Decisions
Why egui?
egui was chosen for its immediate mode rendering approach and Rust integration, making it well-suited for a responsive multi-column UI.
Why nostrdb?
nostrdb provides high-performance local storage and querying for Nostr events, which is essential for a responsive client.
Timeline-centric Design
The codebase is structured around timelines because they provide a natural abstraction for the different types of Nostr content views needed in a column-based interface.
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Run tests:
cargo test - Submit a pull request
Please follow the existing code style and patterns.