Skip to content

Commit a0e1c23

Browse files
authored
add CLAUDE and AGENTS files (#1165)
1 parent 033dbc4 commit a0e1c23

File tree

3 files changed

+238
-154
lines changed

3 files changed

+238
-154
lines changed

AGENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CLAUDE.md

CLAUDE.md

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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+
Treetracker Android is a field data collection app for the Greenstand open source project. The app captures tree growth data in the field, establishing employment for people in extreme poverty through tree planting. Data flows through a pipeline to a verification service.
8+
9+
## Prerequisites
10+
11+
**Required:** Request the `treetracker.keys.properties` file from the #android_chat Slack channel before building. This file contains AWS S3 credentials, API client IDs, and secrets for all build variants.
12+
13+
## Build Variants
14+
15+
Five build variants exist, each with different API endpoints and configurations:
16+
17+
- **dev**: Development variant with relaxed tree data accuracy requirements. Use this for local development.
18+
- **debug**: Standard debug build with test environment settings and blur detection enabled.
19+
- **beta**: Testing variant pointing to test environment. Used for internal releases to testers.
20+
- **prerelease**: Pre-production build using production environment.
21+
- **release**: Production build with minification enabled and production API endpoints.
22+
23+
## Common Commands
24+
25+
### Building
26+
```bash
27+
# Build dev variant (recommended for development)
28+
./gradlew assembleDev
29+
30+
# Build other variants
31+
./gradlew assembleDebug
32+
./gradlew assembleBeta
33+
./gradlew assemblePrerelease
34+
./gradlew assembleRelease
35+
```
36+
37+
### Testing
38+
```bash
39+
# Run all unit tests
40+
./gradlew test
41+
42+
# Run tests for specific variant
43+
./gradlew testDevUnitTest
44+
./gradlew testDebugUnitTest
45+
46+
# Run instrumented tests on connected device
47+
./gradlew connectedDebugAndroidTest
48+
```
49+
50+
### Code Quality
51+
```bash
52+
# Run all checks (includes ktlint, spotless, detekt)
53+
./gradlew check
54+
55+
# Run ktlint only
56+
./gradlew ktlintCheck
57+
58+
# Format code with ktlint
59+
./gradlew ktlintFormat
60+
61+
# Run detekt static analysis
62+
./gradlew detekt
63+
64+
# Apply spotless formatting
65+
./gradlew spotlessApply
66+
```
67+
68+
### Deployment (Fastlane)
69+
```bash
70+
# Setup fastlane
71+
bundle install --path vendor/bundle
72+
fastlane install_plugins
73+
firebase login
74+
```
75+
76+
## Architecture
77+
78+
### Pattern
79+
The app follows **MVVM (Model-View-ViewModel)** architecture:
80+
81+
- **View**: Jetpack Compose UI with reusable components in `view/` package
82+
- **ViewModel**: Per-screen ViewModels manage UI state and business logic
83+
- **Model**: Room database + Retrofit API + Repositories as single source of truth
84+
85+
### Dependency Injection
86+
Koin is used for dependency injection with three main modules in `di/`:
87+
88+
- **AppModule.kt**: ViewModels and application-level dependencies
89+
- **RoomModule.kt**: Database and DAOs
90+
- **NetworkModule.kt**: Retrofit, OkHttp, AWS S3 SDK
91+
92+
### Key Technologies
93+
- **Language**: Kotlin
94+
- **UI**: Jetpack Compose
95+
- **DI**: Koin
96+
- **Networking**: Retrofit + OkHttp
97+
- **Storage**: AWS S3 (images), Room (local database)
98+
- **Async**: Kotlin Coroutines
99+
- **Camera**: CameraX
100+
- **Testing**: JUnit, MockK, Robolectric, Turbine
101+
- **Analytics**: Firebase Analytics + Crashlytics
102+
103+
## Navigation Flows
104+
105+
### Capture Setup Flow
106+
Managed by `CaptureSetupNavigationController`. Dynamic flow defined by the user's organization:
107+
108+
1. **Dashboard****UserSelect** (user selection or creation)
109+
2. Organization-specific setup screens (varies by org)
110+
3. **TreeCapture** (final destination)
111+
112+
When setup completes, step counter, session tracker, and GPS updates are started before entering tree capture.
113+
114+
### Tree Capture Flow
115+
Managed by `CaptureFlowNavigationController`. Dynamic flow configured per organization that can include:
116+
117+
- **TreeCapture**: Main capture screen
118+
- **TreeHeightScreen**: Height measurement (if enabled)
119+
- **TreeImageReview**: Review captured photos
120+
- **SessionNote**: Add notes to capture session
121+
- **TreeDBH**: Diameter at breast height (if enabled)
122+
123+
### Messaging Flow
124+
- **MessagesUserSelect****IndividualMessageList****Chat**/**Announcement**/**Survey**
125+
126+
## Data Sync Architecture
127+
128+
Background sync is handled by `TreeSyncWorker` (a `CoroutineWorker`) that runs `SyncDataUseCase`. The sync process executes in this order:
129+
130+
1. **Sync Messages**: `MessagesRepo.syncMessages()`
131+
2. **Upload Device Config**: `DeviceConfigUploader.upload()`
132+
3. **Upload User Data**: `PlanterUploader.upload()` (includes user images)
133+
4. **Upload Session Data**: `SessionUploader.upload()`
134+
5. **Upload Trees**: `TreeUploader.uploadLegacyTrees()` and `TreeUploader.uploadTrees()`
135+
6. **Upload Location Data**: `UploadLocationDataUseCase.execute()`
136+
137+
### Upload Pattern
138+
All uploaders follow this pattern:
139+
1. Fetch data from Room database
140+
2. Upload images to AWS S3 using `UploadImageUseCase` (if applicable)
141+
3. Update local data with image URLs
142+
4. Create JSON bundle with upload data
143+
5. Upload bundle to AWS S3 via `ObjectStorageClient`
144+
6. Update local data with bundle ID and mark as uploaded
145+
7. Delete local image files (if applicable)
146+
147+
## Package Structure
148+
149+
Main packages under `org.greenstand.android.TreeTracker`:
150+
151+
- `activities/`: Android activities
152+
- `analytics/`: Analytics and exception logging
153+
- `api/`: Retrofit API interfaces and object storage clients
154+
- `application/`: Application class and initialization
155+
- `background/`: Background workers (sync, notifications)
156+
- `camera/`: Camera capture and image review screens
157+
- `capture/`: Tree capture screens and logic
158+
- `dashboard/`: Main dashboard
159+
- `database/`: Room entities, DAOs, migrations
160+
- `di/`: Koin dependency injection modules
161+
- `messages/`: Messaging features (chat, announcements, surveys)
162+
- `models/`: Data models, repositories, business logic
163+
- `navigation/`: Navigation controllers for app flows
164+
- `signup/`: User registration
165+
- `userselect/`: User selection screen
166+
- `usecases/`: Use case classes for business operations
167+
- `view/`: Reusable Compose UI components
168+
169+
## Testing
170+
171+
Tests are located in `app/src/test/` with structure mirroring main source. Key test utilities:
172+
173+
- **MainCoroutineRule.kt**: Custom rule for testing coroutines
174+
- **FakeFileGenerator.kt**: Generate test files for upload testing
175+
- Unit tests use MockK for mocking, Turbine for Flow testing
176+
177+
Run tests for a single class:
178+
```bash
179+
./gradlew test --tests "org.greenstand.android.TreeTracker.capture.TreeCaptureViewModelTest"
180+
```
181+
182+
## Screen Flows
183+
184+
The app has several main screen flows, which are controlled by `CaptureSetupNavigationController` and `CaptureFlowNavigationController`.
185+
186+
**1. Onboarding and Signup:**
187+
188+
* The app starts with the `SplashScreen`.
189+
* From the splash screen, the user might be taken to the `Dashboard`, `Language` selection, or the `SignupFlow`.
190+
* The `SignupFlow` is used for new user registration.
191+
192+
**2. Capture Setup Flow:**
193+
194+
* This flow is managed by `CaptureSetupNavigationController`.
195+
* It starts from the `Dashboard` and navigates to `UserSelect`.
196+
* If a new user is created, it follows a dynamic path defined by the user's organization to set up the capture process.
197+
* This flow ends by navigating to the `TreeCapture` screen.
198+
199+
**3. Tree Capture Flow:**
200+
201+
* This flow is managed by `CaptureFlowNavigationController`.
202+
* It starts on the `TreeCapture` screen.
203+
* The flow for capturing tree data is dynamic and defined by the user's organization. It can include screens like `TreeHeightScreen`, `TreeImageReview`, and `SessionNote`.
204+
* After the capture is complete, the tree data is saved, and the user is returned to the `TreeCapture` screen to capture another tree.
205+
* The user can navigate back to the `Dashboard` from this flow.
206+
207+
**4. Messaging Flow:**
208+
209+
* This flow allows users to communicate with each other.
210+
* It starts from `MessagesUserSelect`, then goes to `IndividualMessageList`.
211+
* From the message list, the user can navigate to a `Chat` screen, an `Announcement` screen, or a `Survey` screen.
212+
213+
## Upload Business Logic
214+
215+
The data upload process is managed by the `TreeSyncWorker`, a `CoroutineWorker` that runs in the background. The worker triggers the `SyncDataUseCase`, which orchestrates the entire upload process.
216+
217+
The upload process is as follows:
218+
219+
1. **Sync Messages:** `MessagesRepo.syncMessages()` is called to sync messages.
220+
2. **Upload Device Config:** `DeviceConfigUploader.upload()` is called to upload the device configuration.
221+
3. **Upload User Data:** `PlanterUploader.upload()` is called to upload user data, including user images.
222+
4. **Upload Session Data:** `SessionUploader.upload()` is called to upload session data.
223+
5. **Upload Trees:** `TreeUploader.uploadLegacyTrees()` and `TreeUploader.uploadTrees()` are called to upload legacy and new trees, respectively.
224+
6. **Upload Location Data:** `UploadLocationDataUseCase.execute()` is called to upload location data.
225+
226+
**General Upload Pattern:**
227+
228+
The uploaders (`TreeUploader`, `PlanterUploader`, `SessionUploader`) follow a similar pattern:
229+
230+
1. **Fetch Data:** Get the data to be uploaded from the local Room database.
231+
2. **Upload Images (if applicable):** Upload images to AWS S3 using the `UploadImageUseCase` and get the image URL.
232+
3. **Update Local Data:** Update the local data with the image URL.
233+
4. **Create JSON Bundle:** Create a JSON bundle containing the data to be uploaded.
234+
5. **Upload Bundle:** Upload the JSON bundle to AWS S3 using the `ObjectStorageClient`.
235+
6. **Update Local Data:** Update the local data with the bundle ID and mark it as uploaded.
236+
7. **Delete Local Images (if applicable):** Delete the local image files that have been uploaded.
237+

gemini.md

Lines changed: 0 additions & 154 deletions
This file was deleted.

0 commit comments

Comments
 (0)