|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +Look4Sat is an open-source, fully offline Android satellite tracker and pass predictor. It tracks 9000+ active |
| 6 | +satellites using TLE/OMM data from Celestrak/SatNOGS, calculates orbital positions via SGP4/SDP4 models, and displays |
| 7 | +passes relative to the user's location. Features include polar radar visualization, SSTV image decoding, satellite |
| 8 | +ground track mapping, and pass predictions up to 10 days ahead. No ads, no tracking, no network required after initial |
| 9 | +data download. |
| 10 | + |
| 11 | +## Architecture |
| 12 | + |
| 13 | +**MVI (Model-View-Intent)** with unidirectional data flow: |
| 14 | +- `State` data class → exposed via `StateFlow` from ViewModel |
| 15 | +- `Action` sealed interface → user intents dispatched to ViewModel's `onAction()` |
| 16 | +- Jetpack Compose UI observes state and recomposes reactively |
| 17 | + |
| 18 | +**Clean Architecture layers:** |
| 19 | + |
| 20 | +| ------------------------ | --------------------------------------------------------------------- | |
| 21 | +| Module | Responsibility | |
| 22 | +|--------------------------|-----------------------------------------------------------------------| |
| 23 | +| `app` | Entry point. Aggregates all modules | |
| 24 | +| `core:data` | Android library. Room DB, OkHttp networking, repo implementations | |
| 25 | +| `core:domain` | Pure Kotlin (JVM). Orbital math (SGP4/SDP4), models, repo contracts | |
| 26 | +| `core:presentation` | Android library. Compose theme, shared UI components, NavKeys | |
| 27 | +| `feature:map` | OSMDroid map with ground tracks | |
| 28 | +| `feature:passes` | Pass predictions and upcoming events | |
| 29 | +| `feature:radar` | Polar radar view of satellite positions, SSTV image decoding | |
| 30 | +| `feature:satellites` | Satellite list, filtering, selection | |
| 31 | +| `feature:settings` | User preferences | |
| 32 | +| ------------------------ | --------------------------------------------------------------------- | |
| 33 | + |
| 34 | +- `feature:*` modules depend only on `core:domain` + `core:presentation`. Features never depend on each other. |
| 35 | + |
| 36 | +## Build & Run |
| 37 | + |
| 38 | +```shell |
| 39 | +# Debug build |
| 40 | +./gradlew assembleDebug |
| 41 | + |
| 42 | +# Release build (minified, shrunk resources) |
| 43 | +./gradlew assembleRelease |
| 44 | + |
| 45 | +# Run tests |
| 46 | +./gradlew test |
| 47 | +``` |
| 48 | + |
| 49 | +- **Min SDK**: 24 | **Target SDK**: 36 | **JDK**: 17 |
| 50 | +- **Gradle**: Uses version catalog (`gradle/libs.versions.toml`) + convention plugins in `build-logic/` |
| 51 | + |
| 52 | +## Key Libraries |
| 53 | + |
| 54 | +- **Compose** (BOM 2026.05.01) + Material3 Adaptive |
| 55 | +- **Navigation3** (type-safe, uses `@Serializable` NavKeys) |
| 56 | +- **Room** (KSP code generation) for local satellite/TLE storage |
| 57 | +- **OkHttp** 5.x for TLE downloads |
| 58 | +- **OSMDroid** for map rendering |
| 59 | +- **Kotlin Serialization** for navigation args and data parsing |
| 60 | +- **Coroutines** + `StateFlow` for async/reactive patterns |
| 61 | + |
| 62 | +## Conventions |
| 63 | + |
| 64 | +- **Minimal dependencies**: Avoid adding libraries when a simple manual solution exists. Fewer deps = less maintenance. |
| 65 | +- **DI**: Manual — ViewModels use companion `factory()` methods with `IMainContainer` interface. |
| 66 | +- **Navigation**: Type-safe Compose Navigation3 with `@Serializable` data classes as nav keys. |
| 67 | +- **State naming**: `<Feature>State` data class + `<Feature>Action` sealed interface per feature. |
| 68 | +- **No feature-to-feature deps**: All cross-feature communication goes through core layers. |
| 69 | +- **Localization**: 7 languages (en, es, ru, si, tr, uk, zh). |
| 70 | + |
| 71 | +## Data Formats & Migration |
| 72 | + |
| 73 | +**TLE vs. OMM/CSV format:** |
| 74 | + |
| 75 | +Look4Sat supports both TLE and OMM (Orbit Mean-Elements Message) formats for backward compatibility: |
| 76 | + |
| 77 | +- **TLE format**: Traditional 3-line element format (deprecated). NORAD catalog numbers are 5-digit integers, which |
| 78 | + are running out of space. Celestrak has signaled that TLE format will eventually be phased out. |
| 79 | +- **OMM/CSV format**: The future standard. CSV files contain the same orbital parameters as TLE but use ISO 8601 |
| 80 | + timestamps and support larger NORAD IDs. Celestrak and SatNOGS already provide OMM data in CSV format. |
| 81 | + |
| 82 | +**Current implementation:** |
| 83 | +- `DataParser.kt` handles both `parseTLEStream()` and `parseCSVStream()` seamlessly |
| 84 | +- TLE data is downloaded from configured sources and stored in Room database |
| 85 | +- When downloading satellite data, the app automatically detects format and parses accordingly |
| 86 | +- Both formats produce identical `OrbitalData` objects, ensuring transparent format switching |
| 87 | + |
| 88 | +**Migration path:** |
| 89 | +As NORAD catalog space becomes constrained, OMM/CSV will become the primary format. Look4Sat is already positioned |
| 90 | +to handle this transition without code changes—existing users can continue using TLE files while new sources transition |
| 91 | +to OMM/CSV automatically. |
| 92 | + |
| 93 | +## Code Style |
| 94 | + |
| 95 | +- Prefer **short, focused functions** — single responsibility, easy to read. |
| 96 | +- **Exceptions**: Composable functions and math-heavy algorithms (SGP4/SDP4) may be longer. |
| 97 | +- Strict code style — no dead code, no unused imports, consistent formatting. |
| 98 | + |
| 99 | +## Roadmap |
| 100 | + |
| 101 | +- **KMP migration**: `core:domain` is to become a fully shareable KMM module. Keep it pure Kotlin/JVM. |
| 102 | + |
| 103 | +## Gotchas |
| 104 | + |
| 105 | +- Orbital math lives in `core:domain/predict/` — it's dense vector math (SGP4/SDP4). Tread carefully. |
| 106 | +- TLE/OMM data must be refreshed weekly for accurate predictions (satellite orbits decay). TLE format is legacy and |
| 107 | + will eventually be deprecated in favor of OMM/CSV as NORAD catalog numbers approach the 5-digit limit. |
| 108 | +- SSTV decoding in `feature:radar` is experimental; image quality depends on signal strength during satellite pass. |
| 109 | +- `build-logic/convention/` contains all shared Gradle configuration — edit there, not in individual modules. |
| 110 | +- ProGuard is enabled for release builds — don't add reflection-based libs or any other dependencies without asking. |
0 commit comments