|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +LunaDraw is a child-centric drawing application (ages 3-8) built with .NET MAUI targeting Windows, Android, iOS, and MacCatalyst. The app features 24+ magical brush effects, shape tools, stamps, undo/redo, layer management, and "Movie Mode" time-lapse replay. |
| 8 | + |
| 9 | +**Important Context:** |
| 10 | + |
| 11 | +- The codebase is heavily AI-generated ("vibe-coded") and can be fragile in places |
| 12 | +- Some canvas functionality was migrated from a working app in `\Legacy\SurfaceBurnCalc` |
| 13 | +- The app is in active development with missing features tracked in `Documentation/MissingFeatures.md` |
| 14 | + |
| 15 | +## Build & Development Commands |
| 16 | + |
| 17 | +### Building |
| 18 | + |
| 19 | +```bash |
| 20 | +# Build the project (Windows target) |
| 21 | +dotnet build LunaDraw.csproj -f net10.0-windows10.0.19041.0 |
| 22 | + |
| 23 | +# Build for specific platform |
| 24 | +dotnet build LunaDraw.csproj -f net10.0-android36.0 |
| 25 | +dotnet build LunaDraw.csproj -f net10.0-ios26.0 |
| 26 | +dotnet build LunaDraw.csproj -f net10.0-maccatalyst26.0 |
| 27 | +``` |
| 28 | + |
| 29 | +### Testing |
| 30 | + |
| 31 | +```bash |
| 32 | +# Run all tests |
| 33 | +dotnet test tests/LunaDraw.Tests/LunaDraw.Tests.csproj |
| 34 | + |
| 35 | +# Run specific test |
| 36 | +dotnet test tests/LunaDraw.Tests/LunaDraw.Tests.csproj --filter "FullyQualifiedName~TestMethodName" |
| 37 | +``` |
| 38 | + |
| 39 | +### Running |
| 40 | + |
| 41 | +- Use Visual Studio 2022 or VS Code with C# Dev Kit and .NET MAUI extensions |
| 42 | +- Select target framework (e.g., `net10.0-windows10.0.19041.0`) |
| 43 | +- Build and Run through IDE |
| 44 | + |
| 45 | +## Architecture |
| 46 | + |
| 47 | +### Core Technologies |
| 48 | + |
| 49 | +- **.NET MAUI** - Cross-platform UI framework |
| 50 | +- **SkiaSharp** - All vector graphics and rendering (primary graphics engine) |
| 51 | +- **ReactiveUI** - MVVM framework and state management using observables |
| 52 | +- **CommunityToolkit.Maui** - Extended MAUI controls and utilities |
| 53 | + |
| 54 | +### Architectural Patterns |
| 55 | + |
| 56 | +#### MVVM with ReactiveUI |
| 57 | + |
| 58 | +- ViewModels inherit from `ReactiveObject` for property change notifications |
| 59 | +- Use `this.RaiseAndSetIfChanged(ref field, value)` for reactive properties |
| 60 | +- Leverage reactive subscriptions for messaging and state changes |
| 61 | + |
| 62 | +#### Messaging & Communication |
| 63 | + |
| 64 | +- **MessageBus** (ReactiveUI's `IMessageBus`): Use sparingly for loosely-coupled broadcast messages between disconnected components |
| 65 | +- **Reactive Observables**: Preferred approach for component communication where possible |
| 66 | +- **Command/Event Pattern**: Fallback when reactive approaches don't fit |
| 67 | +- MessageBus is instance-based (injected via DI), NOT static for testability |
| 68 | + |
| 69 | +#### Dependency Injection |
| 70 | + |
| 71 | +Services registered in `MauiProgram.cs`: |
| 72 | + |
| 73 | +- **Core State**: `IMessageBus`, `NavigationModel`, `SelectionObserver`, `ILayerFacade` |
| 74 | +- **Logic Services**: `ICanvasInputHandler`, `ClipboardMemento`, `IBitmapCache`, `IPreferencesFacade`, `IDrawingStorageMomento` |
| 75 | +- **ViewModels**: Singleton or Transient as appropriate |
| 76 | +- **Pages**: Typically Transient |
| 77 | + |
| 78 | +### Key Architectural Components |
| 79 | + |
| 80 | +#### Drawing Model |
| 81 | + |
| 82 | +- **IDrawableElement**: Base interface for all drawable objects (paths, shapes, stamps, images) |
| 83 | + |
| 84 | + - Supports selection, transforms, visibility, layering (ZIndex), opacity, fill/stroke |
| 85 | + - Each element has `Bounds`, `TransformMatrix`, and methods: `Draw()`, `HitTest()`, `Clone()`, `Translate()`, `Transform()` |
| 86 | + - Concrete implementations: `DrawablePath`, `DrawableEllipse`, `DrawableRectangle`, `DrawableLine`, `DrawableImage`, `DrawableStamps`, `DrawableGroup` |
| 87 | + |
| 88 | +- **Layer**: Container for drawable elements with ReactiveUI observable collections |
| 89 | + |
| 90 | + - Uses **QuadTree spatial indexing** (`QuadTreeMemento<IDrawableElement>`) for efficient spatial queries and rendering |
| 91 | + - No bitmap tiling - renders directly from vector elements |
| 92 | + - Auto-assigns ZIndex to new elements to maintain draw order |
| 93 | + - Supports masking modes, visibility, locking |
| 94 | + |
| 95 | +- **ILayerFacade**: Abstraction for layer management operations |
| 96 | + - Manages `ObservableCollection<Layer>` and current layer state |
| 97 | + - Integrates with `HistoryMemento` for undo/redo |
| 98 | + - Methods: `AddLayer()`, `RemoveLayer()`, `MoveLayer()`, `MoveElementsToLayer()`, `SaveState()` |
| 99 | + |
| 100 | +#### Tool System |
| 101 | + |
| 102 | +- **IDrawingTool**: Interface for all drawing/editing tools |
| 103 | +- Tool implementations: `FreehandTool`, `EraserTool`, `EraserBrushTool`, `FillTool`, `SelectTool`, `LineTool`, `RectangleTool`, `EllipseTool`, `ShapeTool` |
| 104 | +- Tools receive `ToolContext` with canvas state, navigation, layers, and brush settings |
| 105 | +- Input handling delegated to `CanvasInputHandler` which dispatches to active tool |
| 106 | + |
| 107 | +#### View & Viewport Management |
| 108 | + |
| 109 | +- **NavigationModel**: Manages pan/zoom transformations via `ViewMatrix` (SKMatrix) |
| 110 | +- **CanvasInputHandler**: Central touch/mouse input processor |
| 111 | + - Handles multi-touch gestures (pan, zoom, rotate) on canvas and selection |
| 112 | + - Delegates single-touch drawing to active tool |
| 113 | + - Right-click switches to Select tool |
| 114 | + - Applies smoothing to gestures for fluid interaction |
| 115 | +- **MainPage**: Primary page hosting `SKCanvasView` for rendering |
| 116 | + - Subscribes to `CanvasInvalidateMessage` to trigger redraws |
| 117 | + - Manages context menus and flyout panels (brushes, shapes, settings) |
| 118 | + |
| 119 | +#### State Management & History |
| 120 | + |
| 121 | +- **HistoryMemento**: Undo/redo stack for layer states |
| 122 | +- **ClipboardMemento**: Copy/paste buffer for drawable elements |
| 123 | +- **DrawingStorageMomento**: Serialization/deserialization of drawings to file |
| 124 | +- **QuadTreeMemento<T>**: Generic spatial partitioning for efficient hit-testing and culling |
| 125 | + |
| 126 | +## Code Quality & Testing Standards |
| 127 | + |
| 128 | +### Testing with xUnit, Moq |
| 129 | + |
| 130 | +- **Test Format**: Arrange-Act-Assert (AAA) |
| 131 | + - If no `// Arrange` needed, start with `// Act` |
| 132 | +- **Naming**: `Should_When_Returns` format |
| 133 | + - Example: `Should_Set_Sliding_Issued_At_Time_When_Valid_Credentials_Expired_Or_Invalid_Returns_Logout` |
| 134 | +- **Test Instances**: Use class name for instance, NOT 'sut' or arbitrary names |
| 135 | + - Mocks: `mockClassName` (e.g., `mockLayerFacade`) |
| 136 | +- **Assertions**: One assertion per line |
| 137 | +- **Test Types**: Prefer `[Theory]`, `[InlineData]`, `[MemberData]` over multiple `[Fact]` methods. Include negative test cases |
| 138 | + |
| 139 | +### Bug Fixing Workflow |
| 140 | + |
| 141 | +1. **Write test first** to validate the bug exists |
| 142 | +2. Implement the fix |
| 143 | +3. Run test to confirm bug elimination |
| 144 | + |
| 145 | +### Code Style Rules (from .clinerules) |
| 146 | + |
| 147 | +- **NO underscores** in names |
| 148 | +- **NO regions** |
| 149 | +- **NO abbreviations** in variable names or otherwise (use full descriptive names) |
| 150 | +- **NO legacy or duplicate code** - refactor to clean state, remove obsolete code |
| 151 | +- **Static extensions**: Use ONLY for reusable logic (see `Logic/Extensions/`) |
| 152 | + |
| 153 | +### SOLID & Design Principles |
| 154 | + |
| 155 | +Ensure adherence to: |
| 156 | + |
| 157 | +- Single Responsibility Principle (SRP) |
| 158 | +- Open/Closed Principle (OCP) |
| 159 | +- Liskov Substitution Principle (LSP) |
| 160 | +- Interface Segregation Principle (ISP) |
| 161 | +- Dependency Inversion Principle (DIP) |
| 162 | +- DRY (Don't Repeat Yourself) |
| 163 | +- Low Coupling / High Cohesion |
| 164 | +- Separation of Concerns & Modularity |
| 165 | + |
| 166 | +## Project Structure |
| 167 | + |
| 168 | +``` |
| 169 | +LunaDraw/ |
| 170 | +├── Components/ # Reusable UI components and controls |
| 171 | +│ ├── Carousel/ # Gallery carousel implementation |
| 172 | +│ ├── *FlyoutPanel.xaml # Brush, shape, settings panels |
| 173 | +│ └── *.cs # Custom controls (BrushPreview, ShapePreview, etc.) |
| 174 | +├── Converters/ # XAML value converters |
| 175 | +├── Documentation/ # Architecture, features, missing features |
| 176 | +├── Logic/ # Core business logic (non-UI) |
| 177 | +│ ├── Constants/ # App-wide constants |
| 178 | +│ ├── Extensions/ # Static extension methods (SkiaSharp, Preferences) |
| 179 | +│ ├── Handlers/ # Input handling (CanvasInputHandler) |
| 180 | +│ ├── Messages/ # MessageBus message types |
| 181 | +│ ├── Models/ # Domain models (IDrawableElement, Layer, ToolContext, etc.) |
| 182 | +│ ├── Tools/ # IDrawingTool implementations |
| 183 | +│ ├── Utils/ # Utilities (LayerFacade, Mementos, BitmapCache, etc.) |
| 184 | +│ └── ViewModels/ # ReactiveUI ViewModels |
| 185 | +├── Pages/ # MAUI pages (MainPage) |
| 186 | +├── Platforms/ # Platform-specific code |
| 187 | +├── Resources/ # Images, fonts, splash, raw assets |
| 188 | +├── tests/ # Unit tests |
| 189 | +│ └── LunaDraw.Tests/ |
| 190 | +└── MauiProgram.cs # DI registration and app configuration |
| 191 | +``` |
| 192 | + |
| 193 | +## Important Technical Notes |
| 194 | + |
| 195 | +### SkiaSharp Rendering |
| 196 | + |
| 197 | +- All graphics rendered via SkiaSharp (`SKCanvas`, `SKPaint`, `SKPath`) |
| 198 | +- `MainPage.OnCanvasViewPaintSurface`: Main rendering loop |
| 199 | + - Applies `NavigationModel.ViewMatrix` for pan/zoom |
| 200 | + - Iterates layers, uses QuadTree to cull off-screen elements |
| 201 | + - Elements sorted by ZIndex before drawing |
| 202 | + |
| 203 | +### Brush Effects |
| 204 | + |
| 205 | +- 24+ brush effects with custom shaders and blending modes |
| 206 | +- Examples: Glow/Neon (additive blending, bloom), Star Sparkles, Rainbow, Fireworks, Crayon, Spray, Ribbon |
| 207 | +- Brush settings stored in `ToolbarViewModel` and passed via `ToolContext` |
| 208 | + |
| 209 | +### Movie Mode (Time-Lapse) |
| 210 | + |
| 211 | +- Records drawing process in background |
| 212 | +- Playback animates creation of drawing |
| 213 | + |
| 214 | +### Child-Friendly UX Requirements |
| 215 | + |
| 216 | +- Large touch targets (min 2cm x 2cm) |
| 217 | +- Multi-sensory feedback (sounds, animations) |
| 218 | +- Icon-driven, minimal text |
| 219 | +- Visual/audio guidance over explicit instructions |
| 220 | + |
| 221 | +## Legacy & Migration Notes |
| 222 | + |
| 223 | +- Canvas functionality migrated from `\Legacy\SurfaceBurnCalc` (previous working app) |
| 224 | +- Current branch `reactive-carousel-v2` is refactoring carousel infrastructure from SBC to MAUI |
| 225 | +- Code is fragile in places due to AI generation - test thoroughly |
| 226 | + |
| 227 | +## Additional Resources |
| 228 | + |
| 229 | +- **README.md**: Project overview, features, screenshots, setup |
| 230 | +- **Documentation/ArchitectureDesign.md**: Detailed architecture and design requirements |
| 231 | +- **Documentation/Features.md**: Feature specifications |
| 232 | +- **Documentation/MissingFeatures.md**: Pending features and known issues |
| 233 | +- **.clinerules/**: Coding standards and SPARC methodology guidelines |
0 commit comments