diff --git a/README.md b/README.md index 6e793c0ea2..56968ecaf9 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,144 @@ GodTools Android [![codecov](https://codecov.io/gh/CruGlobal/godtools-android/branch/develop/graph/badge.svg)](https://codecov.io/gh/CruGlobal/godtools-android) -# Git LFS +GodTools is a mobile discipleship app built by [Cru](https://www.cru.org/). This repository contains the Android client. -We use [Git LFS](https://git-lfs.com/) for storing Paparazzi snapshots. You will need to setup [Git LFS](https://git-lfs.com/) on your local machine in order to store new paparazzi snapshots or validate existing paparazzi snapshots. +## Requirements -# Crowdin +- **JDK 21** (Temurin) — version specified in `.tool-versions` +- **Android SDK** — compile/target SDK 36, minimum SDK 24 +- **Git LFS** — required for Paparazzi snapshot files -To enable Crowdin translation downloads/uploads, install the [Crowdin CLI tool](https://crowdin.github.io/crowdin-cli/) +## Getting Started + +```bash +# Clone the repo (Git LFS must be installed first) +git clone https://github.com/CruGlobal/godtools-android.git +``` + +### Git LFS + +Paparazzi snapshot images are stored in [Git LFS](https://git-lfs.com/). Install it before cloning or working with snapshot tests: + +```bash +brew install git-lfs # macOS +git lfs install +``` + +## Build & Development + +```bash +# Build the app bundle +./gradlew bundle + +# Run unit tests (all variants) +./gradlew test + +# Run tests for a specific module +./gradlew :library:model:test +./gradlew :app:test + +# Verify Paparazzi snapshot tests (requires Git LFS) +./gradlew verifyPaparazzi + +# Run ktlint (code style checks) +./gradlew :build-logic:ktlintCheck ktlintCheck + +# Run Android lint +./gradlew lint +``` + +> **Paparazzi Snapshots:** Do not record snapshots locally. Trigger the manual GitHub Actions workflow on your feature branch to generate and commit updated screenshots. + +## Project Structure + +``` +app/ # Main application module +build-logic/ # Gradle convention plugins +feature/ # Google Play Dynamic Feature modules +library/ # Core non-UI modules +ui/ # UI and tool-renderer modules +``` + +### `app/` +Main application module — `GodToolsApplication` (Hilt entry point), `DashboardActivity`, Dagger modules in `dagger/`. + +### `library/` +| Module | Purpose | +|---|---| +| `model` | Data models and JSON:API type definitions | +| `db` | Room database, DAOs, and repositories | +| `api` | Retrofit REST and Scarlet WebSocket clients | +| `sync` | WorkManager-based data synchronization | +| `base` | Core utilities, settings, file system abstraction | +| `account` | User authentication | +| `analytics` | Event tracking | +| `download-manager` | Tool download management | +| `initial-content` | Bundled initial content | +| `user-data` | User preferences and state | + +### `ui/` +| Module | Purpose | +|---|---| +| `base` | Shared Compose components and Material 3 theme | +| `base-tool` | Base tool rendering infrastructure | +| `tract-renderer` | Tract tool renderer | +| `lesson-renderer` | Lesson tool renderer | +| `article-renderer` | Article tool renderer | +| `article-aem-renderer` | AEM article tool renderer | +| `cyoa-renderer` | Choose Your Own Adventure renderer | +| `tips-renderer` | Tips renderer | +| `tutorial-renderer` | Tutorial renderer | +| `shortcuts` | App shortcuts UI | +| `qr-code` | QR code feature UI | + +### `feature/` +Google Play Dynamic Feature modules: `bundledcontent` (bundled initial content delivered via Play). + +### `build-logic/` +Gradle convention plugins: `godtools.application-conventions`, `godtools.library-conventions`, `godtools.dynamic-feature-conventions`. + +## Architecture & Key Frameworks + +| Concern | Technology | +|---|---| +| Dependency injection | Hilt (Dagger 2) | +| UI | Jetpack Compose + Material Design 3 | +| Navigation / UI state | [Slack Circuit](https://slackhq.github.io/circuit/) | +| Networking | Retrofit (REST), Scarlet (WebSocket), OkHttp | +| Database | Room | +| Background work | WorkManager | +| Image loading | Coil | +| Dependency versions | `gradle/libs.versions.toml` version catalog | + +**Circuit pattern:** Presenter/UI pairs annotated with `@CircuitInject`. Presenters are `@Composable` functions that return state objects; actions flow through `UiState.eventSink`. + +## Build Variants + +- **Product flavors** (`env` dimension): `stage` (staging API), `production` (production API) +- **Build types**: `debug`, `qa` (inherits debug), `release` +- The `stage` flavor is only available for `debug` and `qa` builds + +## Code Style + +Style is enforced by [ktlint](https://pinterest.github.io/ktlint/) with the `android_studio` code style. + +- Max line length: 120 +- Indent: 4 spaces + +Always run ktlint before committing: + +```bash +./gradlew :build-logic:ktlintCheck ktlintCheck +``` + +## Translations (Crowdin) + +Strings are managed via [Crowdin](https://crowdin.com/). To push/pull translations, install the [Crowdin CLI](https://crowdin.github.io/crowdin-cli/) and set the `CROWDIN_API_TOKEN` environment variable. + +## Contributing + +1. Branch from `develop` and open PRs against `develop` (the default branch). +2. Add unit tests for any new functionality. +3. Run ktlint and unit tests before opening a PR. +4. For UI changes, trigger the Paparazzi snapshot workflow on your branch rather than recording locally.