192 lines
6.3 KiB
Markdown
192 lines
6.3 KiB
Markdown
# Fluffytrix Agent Guidelines
|
|
|
|
## Project Overview
|
|
|
|
Fluffytrix is an Android Matrix chat client with a Discord-like UI. Built with Kotlin, targeting Android 14+ (minSdk 34, targetSdk 36, compileSdk 36).
|
|
|
|
**Package**: `com.example.fluffytrix`
|
|
**Build system**: Gradle with Kotlin DSL, version catalog at `gradle/libs.versions.toml`
|
|
**Container/DI**: Koin
|
|
**State management**: Jetpack Compose StateFlow, ViewModel
|
|
**UI framework**: Jetpack Compose with Material 3 (Dynamic Colors)
|
|
**Protocol**: Trixnity SDK for Matrix
|
|
**Storage**: Room Database, DataStore Preferences
|
|
**Async**: Kotlin Coroutines
|
|
|
|
---
|
|
|
|
## Build Commands
|
|
|
|
```bash
|
|
./gradlew assembleDebug # Build debug APK (minified for performance)
|
|
./gradlew assembleRelease # Build release APK
|
|
./gradlew test # Run unit tests
|
|
./gradlew connectedAndroidTest # Run instrumented tests on device/emulator
|
|
./gradlew testDebugUnitTest --tests "com.example.fluffytrix.ExampleUnitTest" # Run single test
|
|
```
|
|
|
|
**Notes**:
|
|
- Debug builds use R8 with `isDebuggable = true` but strip material-icons-extended and optimize Compose for performance
|
|
- Use `--tests` with Gradle test tasks to run a single test class
|
|
- Instrumented tests require a connected device or emulator
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
**Unit tests**: Located in `app/src/test/java/`, run with `./gradlew test`
|
|
**Instrumented tests**: Located in `app/src/androidTest/java/`, run with `./gradlew connectedAndroidTest`
|
|
|
|
**Single test execution**:
|
|
```bash
|
|
./gradlew testDebugUnitTest --tests "com.example.fluffytrix.*"
|
|
./gradlew app:testDebugUnitTest --tests "ExampleUnitTest"
|
|
```
|
|
|
|
---
|
|
|
|
## Code Style Guidelines
|
|
|
|
### Kotlin Conventions
|
|
|
|
- **Android Official Kotlin style** (`kotlin.code.style=official` in gradle.properties)
|
|
- File naming: `PascalCase.kt` (e.g., `MainViewModel.kt`)
|
|
- Class naming: `PascalCase` (e.g., `MainViewModel`, `AuthRepository`)
|
|
- Function/property naming: `camelCase` (e.g., `sendMessage`, `selectedChannel`)
|
|
- Constant naming: `PascalCase` for top-level constants
|
|
- **Never use underscores in variable names**
|
|
|
|
### Imports
|
|
|
|
- Explicit imports only (no wildcard imports)
|
|
- Group imports: Android/X → Kotlin → Javax/Java → Third-party → Same package
|
|
- Example:
|
|
```kotlin
|
|
import android.os.Bundle
|
|
import androidx.compose.material3.Text
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
import net.folivo.trixnity.client.MatrixClient
|
|
import com.example.fluffytrix.ui.theme.FluffytrixTheme
|
|
```
|
|
|
|
### Types
|
|
|
|
- Prefer `val` over `var` (immutable data)
|
|
- Use `StateFlow<T>` for observable state in ViewModels
|
|
- Use `Flow<T>` for read-only data streams
|
|
- Use `suspend` functions for async operations
|
|
- Use `Result<T>` for operations that can fail
|
|
|
|
### Error Handling
|
|
|
|
- Prefer `try-catch` with silent failure or `?` operators where appropriate
|
|
- In ViewModels, use `catch (_: Exception) { }` or `?:` for graceful degradation
|
|
- Expose error state via `StateFlow<AuthState>` where users need feedback
|
|
- **Never crash the app on recoverable errors**
|
|
|
|
### Compose UI
|
|
|
|
- Use `@Composable` for all UI functions
|
|
- Follow Discord-like layout: space sidebar → channel list → message area → member list
|
|
- Use `MaterialTheme` for consistent theming
|
|
- Prefer `Modifier.padding()` over nested `Box` with margins
|
|
- Use `wrapContentWidth()` and `fillMaxWidth()` appropriately
|
|
- For columnar layouts: `Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(12.dp))`
|
|
|
|
### ViewModels
|
|
|
|
- Inject dependencies via constructor (Koin)
|
|
- Use `viewModelScope` for coroutines
|
|
- Expose state via `StateFlow` (e.g., `val messages: StateFlow<List<MessageItem>>`)
|
|
- Use `MutableStateFlow` for internal state, expose as read-only `StateFlow`
|
|
|
|
### Coroutines
|
|
|
|
- Use `Dispatchers.Default` for CPU-intensive work (parsing, filtering)
|
|
- Use `Dispatchers.IO` for file/network operations
|
|
- Always cancel jobs on ViewModel cleanup: `job?.cancel()`
|
|
- Use `withContext(Dispatchers.Default)` to switch threads explicitly
|
|
|
|
### Data Layer
|
|
|
|
- Use Room for persistent storage (Trixnity uses Room internally)
|
|
- Use DataStore Preferences for small key-value data
|
|
- Prefer Flow-based APIs for reactive data streams
|
|
- Cache expensive operations in ViewModel (e.g., `messageCache`, `memberCache`)
|
|
|
|
### Naming Conventions
|
|
|
|
- State Flow properties: `_name` (private) / `name` (public)
|
|
- Repository class: `AuthService`, `AuthRepository`
|
|
- ViewModel class: `MainViewModel`, `LoginViewModel`
|
|
- UI composable: `MainScreen`, `ChannelList`, `MessageItem`
|
|
- Model data class: `MessageItem`, `ChannelItem`, `SpaceItem`
|
|
- Use `full` property for Matrix IDs (e.g., `userId.full`, `roomId.full`)
|
|
|
|
---
|
|
|
|
## Architecture Patterns
|
|
|
|
**Layered Architecture**:
|
|
```
|
|
ui/ — ViewModels, Screens, Navigation
|
|
data/ — Repositories, local storage, models
|
|
di/ — Koin modules
|
|
ui/theme/ — Material 3 Theme (colors, typography)
|
|
```
|
|
|
|
**Dependency Injection**: Koin with two modules:
|
|
- `appModule`: ViewModels (`viewModel { MainViewModel(...) }`)
|
|
- `dataModule`: singleton services (`single { AuthRepository(...) }`)
|
|
|
|
**UI Flow**:
|
|
1. `FluffytrixNavigation` handles nav graph and session restoration
|
|
2. `MainActivity` hosts the NavHost with `FluffytrixTheme`
|
|
3. ViewModels expose state via StateFlow
|
|
4. Screens observe state with `collectAsState()`
|
|
|
|
---
|
|
|
|
## Key Dependencies (from libs.versions.toml)
|
|
|
|
- **Compose BOM**: `2025.06.00`
|
|
- **Kotlin**: `2.2.10`
|
|
- **AGP**: `9.0.1`
|
|
- **Koin**: `4.1.1`
|
|
- **Trixnity**: `4.22.7`
|
|
- **Ktor**: `3.3.0`
|
|
- **Coroutines**: `1.10.2`
|
|
- **DataStore**: `1.1.7`
|
|
- **Coil**: `3.2.0`
|
|
- **Media3**: `1.6.0`
|
|
|
|
---
|
|
|
|
## Special Notes
|
|
|
|
1. **Matrix IDs**: Use `RoomId`, `UserId` types from Trixnity; access `.full` for string representation
|
|
|
|
2. **MXC URLs**: Convert with `MxcUrlHelper.mxcToDownloadUrl()` and `mxcToThumbnailUrl()`
|
|
|
|
3. **Build Performance**: Debug builds use R8 minification with `isDebuggable = true` to balance speed and debuggability
|
|
|
|
4. **Channel Reordering**: Channel order is saved per-space in DataStore and restored on navigation
|
|
|
|
5. **Encrypted Rooms**: Handle decryption state—messages may appear as `Unable to decrypt` until keys arrive
|
|
|
|
6. **Theme**: Material 3 with Discord-inspired color scheme (primary: `#5865F2`)
|
|
|
|
---
|
|
|
|
## Running Lint/Checks
|
|
|
|
```bash
|
|
./gradlew lintDebug
|
|
./gradlew spotlessCheck
|
|
```
|
|
|
|
## CI/CD
|
|
|
|
- All builds use Gradle wrapper (`./gradlew`)
|
|
- No manual Gradle installation required (project uses Gradle 9.1.0)
|