Add first launch event, share tracking for overview PDF and diagram exports. Add SystemOverviewPDFExporter for A4 PDF generation. Update charger model with new configuration fields and localization for all 5 languages. Refresh app icon assets and CLAUDE.md build instructions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
67 lines
3.4 KiB
Markdown
67 lines
3.4 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Build & Test Commands
|
|
|
|
Use the **Xcode MCP server** tools instead of `xcodebuild` CLI:
|
|
|
|
- **List windows first**: Always run `mcp__xcode__XcodeListWindows` to find the correct `tabIdentifier` — it changes depending on which Xcode windows are open.
|
|
- **Build**: `mcp__xcode__BuildProject`
|
|
- **Run all tests**: `mcp__xcode__RunAllTests`
|
|
- **Check errors**: `mcp__xcode__GetBuildLog` (severity: `error`) or `mcp__xcode__XcodeListNavigatorIssues`
|
|
|
|
No external dependencies beyond the Xcode toolchain.
|
|
|
|
## Architecture
|
|
|
|
**SwiftUI + SwiftData app** for sizing low-voltage electrical conductors (boats, RVs, off-grid).
|
|
|
|
### Data Model Hierarchy
|
|
|
|
`ElectricalSystem` (top-level container) owns collections of:
|
|
- `SavedLoad` — individual electrical loads with wire sizing parameters
|
|
- `SavedBattery` — battery banks with chemistry-specific capacity rules
|
|
- `SavedCharger` — charging equipment specs
|
|
|
|
All are `@Model` classes persisted via SwiftData. The container is configured in `CableApp.swift` and injected into the SwiftUI environment.
|
|
|
|
### Key Layers
|
|
|
|
- **Calculation engine** (`Loads/ElectricalCalculations.swift`): Pure static functions for wire cross-section sizing, voltage drop, power loss, and fuse recommendations. Uses copper resistivity (0.017 Ω·mm²/m) with a 5% max voltage drop constraint. Supports both metric (mm²) and imperial (AWG) wire standards.
|
|
- **CableCalculator** (`Loads/CableCalculator.swift`): ObservableObject wrapper that bridges the calculation engine to SwiftUI views.
|
|
- **App-wide state**: `UnitSystemSettings` (metric/imperial, persisted to UserDefaults) and `StoreKitManager` (subscription status) are injected as `@EnvironmentObject`.
|
|
|
|
### Navigation Flow
|
|
|
|
`SystemsView` (root list) → `LoadsView` (per-system TabView with 4 tabs: Overview, Components, Batteries, Chargers) → individual editor modals for each entity type.
|
|
|
|
### Feature Organization
|
|
|
|
Each feature has its own directory under `Cable/`: `Loads/`, `Systems/`, `Batteries/`, `Chargers/`, `Overview/`, `Paywall/`. Models and views for each feature live together.
|
|
|
|
## Code Style
|
|
|
|
- 4-space indentation, trailing commas on multiline collections, 120-char soft line limit
|
|
- `UpperCamelCase` for types, `lowerCamelCase` for methods/properties
|
|
- Test naming: `testScenario_expectedResult`
|
|
- Commit messages: short imperative subjects under 50 characters
|
|
|
|
## Localization
|
|
|
|
5 languages: English (base), German, Spanish, French, Dutch. Translation files are in `*.lproj/Localizable.strings` and `Localizable.stringsdict`.
|
|
|
|
- Use `String(localized:defaultValue:)` — **not** `NSLocalizedString`. The `defaultValue` serves as English fallback and avoids showing raw keys when a Localizable.strings entry is missing.
|
|
- When adding new user-facing strings, add translations to **all 5** Localizable.strings files immediately.
|
|
|
|
## PDF Export Pattern
|
|
|
|
PDF exports use `UIGraphicsPDFRenderer` with A4 portrait format. The pattern is:
|
|
- **Exporter struct** (e.g. `SystemOverviewPDFExporter`, `SystemBillOfMaterialsPDFExporter`) with snapshot data types — keeps Core Graphics rendering isolated from SwiftUI/SwiftData.
|
|
- **ShareSheet** triggered via `@State` item binding in the parent view.
|
|
- **Toolbar button** (not inline content) for the export action.
|
|
|
|
## StoreKit
|
|
|
|
Subscription product IDs: `app.voltplan.cable.weekly`, `app.voltplan.cable.yearly`. Pro features are gated via `StoreKitManager.isPro`.
|