Skip to content

Latest commit

 

History

History
118 lines (82 loc) · 4.14 KB

File metadata and controls

118 lines (82 loc) · 4.14 KB

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.
  • 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 for navigation and 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 FooEvents.
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 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 RoomJoinedRoom 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).