# Contributing to Ziya-Slint Thank you for your interest in contributing to Ziya-Slint! This guide outlines our development approach, coding standards, and best practices for the desktop trading application. ## Project Overview Ziya-Slint is a desktop trading application built with Rust and Slint UI framework, designed for cryptocurrency trading with real-time market data and portfolio management. ## Development Philosophy We follow these core principles: 1. **KISS Principle** - Keep code simple and straightforward 2. **Explicit Error Handling** - Never use dummy types or unfinished code 3. **Real-world Ready** - All code should be production-ready 4. **Async-first** - Prefer tokio over std for async operations 5. **Type Safety** - Leverage Rust's type system for correctness 6. **Desktop UX** - Native desktop app behavior and performance ## Getting Started ### Prerequisites - Rust 2024 Edition (see `rust-toolchain.toml`) - Just command runner (for development tasks) - Redis (for data caching) - Git and Git-cliff (for development workflow) ### Initial Setup 1. Clone the repository 2. Copy configuration files: ```bash cp Config.example.toml Config.toml ``` 3. Install development dependencies: ```bash just install-deps ``` 4. Verify setup: ```bash just test just clippy ``` ### Development Workflow We use `just` for common development tasks: ```bash # List all available commands just # Development with hot reloading just dev # Building just build # Build with dev features just build-prod # Build with prod features # Quality assurance just test # Run tests just clippy # Run linter just fmt # Format code just check # Check code for errors just clean # Clean build artifacts ``` ## Coding Standards ### Error Handling We use strict error handling patterns. **Never** use: - Dummy types or results - Placeholder implementations - TODO comments in production code **Always** use our error handling pattern: ```rust use crate::err_with_loc; use crate::error::Result; // Import the Result type use crate::error::Result; // Use map_err before ? operator let result = some_operation() .map_err(|e| { error!("operation_failed: {}", e); err_with_loc!(AppError::OperationFailed(format!("operation_failed: {}", e))) })?; ``` ### Async Programming - **Use tokio** instead of std for async operations - Follow the actors pattern from [this guide](https://ryhl.io/blog/actors-with-tokio/) - **Never** use `tokio::spawn` with UI components directly - **Always** use `slint::invoke_from_event_loop` for UI updates from background tasks ### Code Formatting We use `rustfmt` with specific configuration (see `rustfmt.toml`): - Max width: 120 characters - Use field init shorthand - Reorder imports and impl items - Group imports by StdExternalCrate - Prefer same line braces Run formatting: ```bash just fmt ``` ## Architecture: Feature-Sliced Design (FSD) We follow **Feature-Sliced Design (FSD)** methodology for frontend architecture: ### FSD Layer Structure ``` ui/ ├── app/ # Application layer - root, global setup ├── pages/ # Page layer - complete screens ├── widgets/ # Widget layer - composite UI blocks ├── entities/ # Entity layer - business entities ├── features/ # Feature layer - user interactions └── shared/ # Shared layer - reusable resources ├── ui/ # UI components ├── types/ # Type definitions └── design-system/ # Theme, tokens, etc. ``` ### FSD Rules & Guidelines 1. **Import Rule**: Higher layers can only import from lower layers - ✅ `app/` → `pages/` → `widgets/` → `entities/` → `features/` → `shared/` - ❌ Never import from higher layers 2. **Layer Responsibilities**: - **App**: Global providers, routing, application setup - **Pages**: Complete screens, page-level logic - **Widgets**: Composite UI blocks (navigation, forms, cards) - **Entities**: Business entities (token, user, market data) - **Features**: User interactions (login, trading, portfolio management) - **Shared**: Reusable resources (UI kit, utilities, constants) 3. **Slicing by Features**: Each feature should be self-contained ``` features/ ├── authentication/ │ ├── ui/ # Login components │ ├── model/ # Auth state │ └── api/ # Auth API calls └── trading/ ├── ui/ # Trading components ├── model/ # Trading state └── api/ # Trading API calls ``` 4. **Component Composition**: Build from bottom-up ```slint // shared/ui/button/ export component Button { /* base button */ } // widgets/navigation/ import { Button } from "../../shared/ui/button/"; export component NavigationWidget { Button { /* composed navigation */ } } // pages/dashboard/ import { NavigationWidget } from "../../widgets/navigation/"; export component Dashboard { NavigationWidget { /* page composition */ } } ``` 5. **State Management**: Follow unidirectional data flow - Global state in `app/` layer - Feature state in respective `features/` slices - Pass data down, emit events up 6. **Design System**: Centralized in `shared/design-system/` - Theme tokens and variables - Consistent spacing, colors, typography - Reusable UI components ## Slint UI Development ### Threading & State Management **Critical Pattern for Slint + Tokio:** ```rust // Background work in Rust tokio::spawn(async move { let result = do_background_work().await; // Update UI from main thread following FSD data flow let _ = slint::invoke_from_event_loop(move || { if let Some(ui) = ui_weak.upgrade() { // Update flows from app → pages → widgets → shared ui.update_global_state(result); } }); }); ``` ### Component Development Guidelines 1. **Start with Shared Layer**: Build reusable components first ```slint // shared/ui/loading/loading.slint export component LoadingSpinner { // Base loading component } ``` 2. **Compose in Widgets**: Create business-specific blocks ```slint // widgets/token-card/index.slint import { LoadingSpinner } from "../../shared/ui/loading/"; export component TokenCard { LoadingSpinner { /* token-specific loading */ } } ``` 3. **Integrate in Pages**: Assemble complete screens ```slint // pages/dashboard/index.slint import { TokenCard } from "../../widgets/token-card/"; export component Dashboard { TokenCard { /* dashboard context */ } } ``` 4. **Wire in App**: Handle global state and routing ```slint // app/index.slint import { Dashboard } from "../pages/dashboard/"; export component App { if current-page == "dashboard": Dashboard { } } ``` ### File Naming Conventions - Use `index.slint` for main component exports - Use kebab-case for file names: `token-card.slint` - Use PascalCase for component names: `TokenCard` ### Property & Callback Flow - Properties flow down: `app → pages → widgets → shared` - Callbacks flow up: `shared → widgets → pages → app` - Keep callback interfaces simple and focused ## FSD Best Practices ### ✅ Do: - Keep components focused on single responsibility - Use semantic component names that reflect business domain - Extract common patterns to `shared/` layer - Implement loading and error states consistently - Use TypeScript-like typing through Slint properties - Follow consistent import paths relative to FSD structure ### ❌ Don't: - Import from higher layers (breaks FSD hierarchy) - Put business logic directly in UI components - Create circular dependencies between features - Hardcode values that should be in design system - Mix concerns (UI logic with business logic) - Create deep nesting beyond FSD layers ### Common Anti-patterns to Avoid: ```slint // ❌ BAD: Widget importing from pages // widgets/header/index.slint import { Dashboard } from "../../pages/dashboard/"; // Wrong! // ❌ BAD: Shared component with business logic // shared/ui/button/index.slint export component Button { // Don't put trading logic here! clicked => { execute_trade(); } } // ✅ GOOD: Proper callback delegation // shared/ui/button/index.slint export component Button { callback clicked(); } // ✅ GOOD: Business logic in appropriate layer // features/trading/ui/trade-button.slint import { Button } from "../../../shared/ui/button/"; export component TradeButton { Button { clicked => { handle_trade_click(); } } } ``` ## Testing ### Unit Tests ```bash just test ``` ### Integration Tests - Test UI components with mock data - Test service layer integration - Use feature flags for test environments ### Feature Testing ```bash # Run with specific features cargo test --features dev cargo test --features prod ``` ## UI/UX Principles We follow comprehensive usability guidelines: 1. **10 Usability Heuristics** - Nielsen's principles 2. **Gestalt Principles** - Visual hierarchy and grouping 3. **Accessibility** - Support for different user needs 4. **Simplicity** - Minimize cognitive load 5. **Desktop Patterns** - Native desktop app behavior ### Key Requirements: - Responsive design within window constraints (1080x800 - 1920x1080) - Proper error messaging in plain language - Loading states with progress indication - Keyboard navigation support - Native desktop interactions ## Submission Guidelines ### Branch Naming Use descriptive names: - `feat/shared/button-component` - New shared component - `feat/pages/dashboard-redesign` - Page-level changes - `feat/features/trading-flow` - Feature implementation - `fix/widgets/token-card-loading` - Bug fixes - `refactor/shared/design-system` - Code improvements ### Commit Messages Be descriptive: ``` feat(shared): add loading spinner component - Implement reusable loading spinner in shared/ui - Add animation and theme support - Export from shared layer for use in widgets fix(pages): resolve dashboard layout overflow - Fix token card grid overflow in dashboard - Improve responsive behavior for small windows - Add proper scrolling for token list ``` ### Code Review Checklist **General:** - [ ] Follows error handling patterns - [ ] Uses tokio for async operations - [ ] Includes proper logging - [ ] Formatted with rustfmt - [ ] Passes all tests - [ ] Updates documentation if needed **FSD-Specific:** - [ ] Components placed in correct FSD layer - [ ] Import dependencies only from lower layers - [ ] Properties flow down, callbacks flow up - [ ] No direct business logic in UI components - [ ] Reusable components in `shared/` layer - [ ] Feature-specific logic in `features/` layer **UI/UX:** - [ ] Follows design system patterns - [ ] Implements proper loading states - [ ] Handles error states gracefully - [ ] Supports keyboard navigation - [ ] Responsive within window constraints ## Development Environment ### Recommended Tools - **IDE**: VS Code with rust-analyzer and Slint extension - **Debugging**: Use tracing for structured logging - **File Watching**: `watchexec` for auto-reload during development - **Hot Reloading**: `just dev` for development workflow ### Common Issues #### Slint Compilation Errors If you encounter field offset errors with watchexec: ```bash cargo clean # Then rebuild ``` #### Threading Issues Remember: Slint UI components are not `Send`. Always use `slint::invoke_from_event_loop` for UI updates from background tasks. #### Hot Reloading For the best development experience: ```bash just dev ``` This watches both `src/` and `ui/` directories and automatically rebuilds. ## Documentation - **Component APIs**: Document with clear examples - **Architecture**: Update this guide when patterns change - **Configuration**: Document all config options - **UI Components**: Maintain design system documentation ## Getting Help 1. Check existing documentation 2. Search closed issues on GitHub 3. Ask in project discussions 4. Check Slint documentation for UI issues ## Code of Conduct - Be respectful and inclusive - Focus on constructive feedback - Help others learn and grow - Maintain professional communication --- By following these guidelines, you help maintain code quality and ensure smooth collaboration on the Ziya-Slint desktop application. Thank you for contributing! 🚀