Create AGENTS.md
This commit is contained in:
118
AGENTS.md
Normal file
118
AGENTS.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# AGENTS.md — Element X Android
|
||||||
|
|
||||||
|
> **Repo:** `element-hq/element-x-android` — Android Matrix client (Compose UI + `matrix-rust-sdk`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Strong Conventions
|
||||||
|
|
||||||
|
PRs must meet these rules.
|
||||||
|
|
||||||
|
### Code Style
|
||||||
|
|
||||||
|
- Style enforced by **Editor config** (`.editorconfig`).
|
||||||
|
- Set "Hard wrap at" to 160 chars in Android Studio.
|
||||||
|
|
||||||
|
### PII & Logging
|
||||||
|
|
||||||
|
- We use **Timber** for logging. Never use `android.util.Log`.
|
||||||
|
- **Never log secrets, passwords, keys, or user content** (e.g. message bodies).
|
||||||
|
- Matrix IDs (User IDs, Room IDs, Event IDs) are safe to log.
|
||||||
|
|
||||||
|
### Strings & Localisation
|
||||||
|
|
||||||
|
- Default localisation: `en` (en-GB strings), shared with Element X iOS via [Localazy](https://localazy.com/p/element).
|
||||||
|
- **Never edit `localazy.xml`** — it is auto-generated and overwritten.
|
||||||
|
- New English strings go in **`temporary.xml`**. The core team imports these to Localazy.
|
||||||
|
- **Key naming**:
|
||||||
|
- Cross-screen verbs: `action_` (e.g., `action_copy`).
|
||||||
|
- Common nouns/other: `common_` (e.g., `common_error`).
|
||||||
|
- Accessibility: `a11y_`.
|
||||||
|
- Screen-specific: `screen_<name>_<key>` (e.g., `screen_onboarding_welcome_title`).
|
||||||
|
- Errors: `error_` prefix.
|
||||||
|
- Platform-specific: `_ios` or `_android` suffix.
|
||||||
|
- Placeholders: Use numbered form `%1$s`, `%2$d`.
|
||||||
|
|
||||||
|
### Previews
|
||||||
|
|
||||||
|
- Create previews for **all main states** of a Composable.
|
||||||
|
- Use `@PreviewsDayNight` for consistency.
|
||||||
|
- Use `PreviewParameterProvider` (e.g., `FooStateProvider`) to provide states.
|
||||||
|
- Wrap previews in `ElementPreview { ... }`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pull Request Guidelines
|
||||||
|
|
||||||
|
- Use sentence-style commit/PR messages (no conventional commits).
|
||||||
|
- Apply exactly **one** `PR-` label for changelog categorization.
|
||||||
|
- PR title = changelog entry — make it descriptive; no "Fixes #…" prefixes.
|
||||||
|
- Include screenshots or screen recordings for any UI changes.
|
||||||
|
- Keep PRs focused; split changes over 1000 lines.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
Common Gradle tasks:
|
||||||
|
- Build: `./gradlew assembleDebug`
|
||||||
|
- Unit Tests: `./gradlew test`
|
||||||
|
- Lint: `./gradlew lint`
|
||||||
|
- Format: `./gradlew ktlintFormat`
|
||||||
|
- Update Docs TOC: `./gradlew generateDocsToc`
|
||||||
|
|
||||||
|
### Gradle Modules
|
||||||
|
|
||||||
|
Features follow a 3-module structure:
|
||||||
|
- `features/foo/api`: Public interfaces and data classes.
|
||||||
|
- `features/foo/impl`: Internal implementation, Presenter, and View.
|
||||||
|
- `features/foo/test`: Test fakes and utilities.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture: Appyx + Molecule
|
||||||
|
|
||||||
|
We use [Appyx](https://bumble-tech.github.io/appyx/) for navigation and [Molecule](https://github.com/cashapp/molecule) for Presenters.
|
||||||
|
|
||||||
|
### Files Per Screen (`Foo`)
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
| :--- | :--- |
|
||||||
|
| `FooNode.kt` | Appyx Node: Handles navigation and wires the Presenter to the View. |
|
||||||
|
| `FooPresenter.kt` | A `@Composable` function that produces `FooState` from `FooEvent`s. |
|
||||||
|
| `FooView.kt` | Stateless Composable rendering the UI from `FooState`. |
|
||||||
|
| `FooState.kt` | Data class representing the immutable UI state. |
|
||||||
|
| `FooEvent.kt` | Sealed interface for UI actions sent to the Presenter. |
|
||||||
|
| `FooStateProvider.kt` | Provides sample states for Previews and Screenshot tests. |
|
||||||
|
| `FooPresenterTest.kt` | Unit tests for the Presenter logic using Turbine. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependency Injection (Metro)
|
||||||
|
|
||||||
|
- We use [Metro](https://zacsweers.github.io/metro/) for DI.
|
||||||
|
- Inject via constructor parameters using `@Inject`.
|
||||||
|
- Use `@AssistedInject` and `@AssistedFactory` for components requiring runtime arguments (like Navigators or IDs).
|
||||||
|
- Use `@ContributesBinding(AppScope::class)` for singleton-like services.
|
||||||
|
- Use `@ContributesNode(RoomScope::class)` for Appyx Nodes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Compound Design System
|
||||||
|
|
||||||
|
Always prefer Compound components and tokens from `libraries/compound/` module.
|
||||||
|
|
||||||
|
- **Colours**: `ElementTheme.colors.textPrimary`, `ElementTheme.colors.bgCanvasDefault`.
|
||||||
|
- **Typography**: `ElementTheme.typography.fontBodyMdRegular`.
|
||||||
|
- **Icons**: Use `CompoundIcons.IconName()` (e.g., `CompoundIcons.UserProfileSolid()`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Rust SDK Layer
|
||||||
|
|
||||||
|
We wrap the `matrix-rust-sdk` to isolate the UI from the underlying SDK.
|
||||||
|
- Naming: SDK `Room` → `JoinedRoom` or `RoomInfo`.
|
||||||
|
- Type Mapping: Map Rust SDK types to Kotlin data classes in the `api` module to avoid leaking `MatrixRustSDK` into the UI.
|
||||||
|
- Always follow Kotlin naming conventions (e.g., `userId` instead of `userID`).
|
||||||
Reference in New Issue
Block a user