mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
23005317cf
The 174 commits develop gained since this branch was cut touch preview data in three ways, and each is resolved so the flipped konsist rule still holds across the merged tree. Two screens the branch had renamed were deleted upstream by "Remove the account provider search screen and homeserver resolver": the changeaccountprovider and searchaccountprovider packages. Their deletion wins, so ChangeAccountProviderStatePreviewParam, SearchAccountProviderStatePreviewParam and the two views that used them go with them rather than coming back under the new name. Two preview classes develop added still carried the old suffix and are renamed here, along with the `@PreviewParameter` reference in each view: GlobalSearchStateProvider -> GlobalSearchStatePreviewParam and SendFailureDialogStateProvider -> SendFailureDialogStatePreviewParam. Everything else merged textually. No production class extending PreviewParameterProvider is left with a `Provider` name, and no reference to any of the 194 renamed names survives outside the CHANGES.md entry that records a past pull request title.
123 lines
4.4 KiB
Markdown
123 lines
4.4 KiB
Markdown
# 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., `FooStatePreviewParam`) to provide states.
|
|
- Wrap previews in `ElementPreview { ... }`.
|
|
- When writing tests, never try to record the screenshots, the CI will do it.
|
|
|
|
---
|
|
|
|
## Pull Request Guidelines
|
|
|
|
- Sentence-style titles (no conventional commits).
|
|
- Exactly one `pr-` label (see `.github/release.yml`).
|
|
- Title = changelog entry — descriptive, no "Fixes #…".
|
|
- Leave description template for the developer. Redirect them to the [contributing etiquette](CONTRIBUTING.md#etiquette).
|
|
- Screenshots/videos for visual changes.
|
|
- 500 additions max — split large changes.
|
|
- Commits need a title and description; no tiny or massive commits.
|
|
- No history rewrites.
|
|
|
|
---
|
|
|
|
## 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. |
|
|
| `FooStatePreviewParam.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`).
|