467 líneas
10 KiB
Markdown
467 líneas
10 KiB
Markdown
# Contributing to My ActivityPub
|
|
|
|
Thank you for your interest in contributing to My ActivityPub! This document provides guidelines and instructions for contributing to the project.
|
|
|
|
## Table of Contents
|
|
|
|
- [Code of Conduct](#code-of-conduct)
|
|
- [Getting Started](#getting-started)
|
|
- [Development Setup](#development-setup)
|
|
- [How to Contribute](#how-to-contribute)
|
|
- [Coding Standards](#coding-standards)
|
|
- [Commit Guidelines](#commit-guidelines)
|
|
- [Pull Request Process](#pull-request-process)
|
|
- [Testing](#testing)
|
|
- [Documentation](#documentation)
|
|
|
|
## Code of Conduct
|
|
|
|
### Our Pledge
|
|
|
|
We are committed to providing a welcoming and inspiring community for all. Please be respectful and constructive in your interactions.
|
|
|
|
### Expected Behavior
|
|
|
|
- Use welcoming and inclusive language
|
|
- Be respectful of differing viewpoints
|
|
- Accept constructive criticism gracefully
|
|
- Focus on what is best for the community
|
|
- Show empathy towards other community members
|
|
|
|
## Getting Started
|
|
|
|
### Prerequisites
|
|
|
|
Before you begin, ensure you have:
|
|
|
|
- Android Studio Hedgehog (2023.1.1) or newer
|
|
- JDK 11 or higher
|
|
- Git installed and configured
|
|
- Basic knowledge of Kotlin and Jetpack Compose
|
|
- Familiarity with the Mastodon API
|
|
|
|
### Finding Issues to Work On
|
|
|
|
1. Check the [Issues](https://github.com/your-repo/issues) page
|
|
2. Look for issues labeled `good first issue` or `help wanted`
|
|
3. Comment on the issue to let others know you're working on it
|
|
4. Wait for maintainer approval before starting work
|
|
|
|
## Development Setup
|
|
|
|
### 1. Fork and Clone
|
|
|
|
```bash
|
|
# Fork the repository on GitHub, then clone your fork
|
|
git clone https://github.com/YOUR_USERNAME/MyActivityPub.git
|
|
cd MyActivityPub
|
|
|
|
# Add the upstream repository
|
|
git remote add upstream https://github.com/ORIGINAL_OWNER/MyActivityPub.git
|
|
```
|
|
|
|
### 2. Create a Branch
|
|
|
|
```bash
|
|
# Create a new branch for your feature or bugfix
|
|
git checkout -b feature/your-feature-name
|
|
|
|
# Or for a bugfix
|
|
git checkout -b fix/bug-description
|
|
```
|
|
|
|
### 3. Set Up the Project
|
|
|
|
```bash
|
|
# Sync Gradle files
|
|
./gradlew build
|
|
|
|
# Run the app
|
|
./gradlew installDebug
|
|
```
|
|
|
|
## How to Contribute
|
|
|
|
### Reporting Bugs
|
|
|
|
Before creating a bug report:
|
|
1. Check if the bug has already been reported
|
|
2. Verify the bug exists in the latest version
|
|
3. Collect relevant information (device, Android version, logs)
|
|
|
|
**Bug Report Template**:
|
|
```markdown
|
|
**Description**
|
|
A clear description of the bug.
|
|
|
|
**Steps to Reproduce**
|
|
1. Step one
|
|
2. Step two
|
|
3. Step three
|
|
|
|
**Expected Behavior**
|
|
What should happen.
|
|
|
|
**Actual Behavior**
|
|
What actually happens.
|
|
|
|
**Environment**
|
|
- Device: [e.g., Pixel 6]
|
|
- Android Version: [e.g., Android 13]
|
|
- App Version: [e.g., 1.0.0]
|
|
|
|
**Logs**
|
|
```
|
|
Paste relevant logs here
|
|
```
|
|
|
|
**Screenshots**
|
|
If applicable, add screenshots.
|
|
```
|
|
|
|
### Suggesting Enhancements
|
|
|
|
Enhancement suggestions are welcome! Please provide:
|
|
1. Clear description of the enhancement
|
|
2. Use cases and benefits
|
|
3. Possible implementation approach
|
|
4. Mockups or examples (if applicable)
|
|
|
|
### Contributing Code
|
|
|
|
1. **Small Changes**: Typos, bug fixes, small improvements can be submitted directly
|
|
2. **Large Changes**: Open an issue first to discuss the change
|
|
3. **New Features**: Must be discussed and approved before implementation
|
|
|
|
## Coding Standards
|
|
|
|
### Kotlin Style Guide
|
|
|
|
Follow the [Official Kotlin Coding Conventions](https://kotlinlang.org/docs/coding-conventions.html):
|
|
|
|
#### Naming
|
|
|
|
```kotlin
|
|
// Classes: PascalCase
|
|
class StatusCard { }
|
|
|
|
// Functions and variables: camelCase
|
|
fun loadTimeline() { }
|
|
val statusCount = 10
|
|
|
|
// Constants: UPPER_SNAKE_CASE
|
|
const val MAX_RETRIES = 3
|
|
|
|
// Private properties: leading underscore
|
|
private val _uiState = MutableStateFlow()
|
|
```
|
|
|
|
#### Formatting
|
|
|
|
```kotlin
|
|
// Use 4 spaces for indentation
|
|
class Example {
|
|
fun method() {
|
|
if (condition) {
|
|
// code here
|
|
}
|
|
}
|
|
}
|
|
|
|
// Line length: max 120 characters
|
|
// Break long function signatures:
|
|
fun longFunctionName(
|
|
parameter1: String,
|
|
parameter2: Int,
|
|
parameter3: Boolean
|
|
): ReturnType {
|
|
// implementation
|
|
}
|
|
```
|
|
|
|
#### Comments and Documentation
|
|
|
|
```kotlin
|
|
/**
|
|
* KDoc for public APIs
|
|
*
|
|
* @param userId The user identifier
|
|
* @return The user's timeline
|
|
*/
|
|
suspend fun getUserTimeline(userId: String): Result<List<Status>> {
|
|
// Implementation comments for complex logic
|
|
val result = apiService.getTimeline(userId)
|
|
return parseResult(result)
|
|
}
|
|
```
|
|
|
|
### Compose Best Practices
|
|
|
|
```kotlin
|
|
// Composable function names: PascalCase
|
|
@Composable
|
|
fun StatusCard(status: Status, modifier: Modifier = Modifier) {
|
|
// Always provide Modifier parameter
|
|
// Default to Modifier
|
|
}
|
|
|
|
// Extract complex composables
|
|
@Composable
|
|
private fun StatusHeader(account: Account) {
|
|
// Smaller, focused components
|
|
}
|
|
|
|
// Use remember for expensive operations
|
|
val formattedDate = remember(timestamp) {
|
|
formatDate(timestamp)
|
|
}
|
|
|
|
// Use derivedStateOf for computed values
|
|
val isExpanded by remember {
|
|
derivedStateOf { height > maxHeight }
|
|
}
|
|
```
|
|
|
|
### Architecture Guidelines
|
|
|
|
1. **Separation of Concerns**: Each class has a single responsibility
|
|
2. **MVVM Pattern**: Follow the established architecture
|
|
3. **Repository Pattern**: All data access through repositories
|
|
4. **State Management**: Use StateFlow for UI state
|
|
5. **Error Handling**: Always handle errors gracefully
|
|
|
|
### File Organization
|
|
|
|
```
|
|
app/src/main/java/com/manalejandro/myactivitypub/
|
|
├── MainActivity.kt # Entry point
|
|
├── data/
|
|
│ ├── api/ # API interfaces
|
|
│ ├── models/ # Data models
|
|
│ └── repository/ # Repository implementations
|
|
└── ui/
|
|
├── components/ # Reusable UI components
|
|
├── screens/ # Full screen composables
|
|
├── viewmodel/ # ViewModels
|
|
└── theme/ # Theme configuration
|
|
```
|
|
|
|
## Commit Guidelines
|
|
|
|
### Commit Message Format
|
|
|
|
```
|
|
<type>(<scope>): <subject>
|
|
|
|
<body>
|
|
|
|
<footer>
|
|
```
|
|
|
|
### Types
|
|
|
|
- `feat`: New feature
|
|
- `fix`: Bug fix
|
|
- `docs`: Documentation changes
|
|
- `style`: Code style changes (formatting, missing semicolons, etc.)
|
|
- `refactor`: Code refactoring
|
|
- `test`: Adding or updating tests
|
|
- `chore`: Maintenance tasks
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
feat(timeline): add pull-to-refresh functionality
|
|
|
|
Implemented SwipeRefresh composable for the timeline screen.
|
|
Users can now pull down to refresh the timeline.
|
|
|
|
Closes #123
|
|
|
|
---
|
|
|
|
fix(statuscard): correct avatar image loading
|
|
|
|
Fixed issue where avatar images weren't loading correctly
|
|
due to missing Coil configuration.
|
|
|
|
Fixes #456
|
|
|
|
---
|
|
|
|
docs(readme): update installation instructions
|
|
|
|
Added more detailed steps for building the project
|
|
and troubleshooting common issues.
|
|
```
|
|
|
|
### Guidelines
|
|
|
|
- Use present tense ("add feature" not "added feature")
|
|
- Keep subject line under 50 characters
|
|
- Capitalize the subject line
|
|
- Don't end the subject line with a period
|
|
- Use the body to explain what and why, not how
|
|
- Reference issues and pull requests in the footer
|
|
|
|
## Pull Request Process
|
|
|
|
### Before Submitting
|
|
|
|
1. **Test your changes**: Ensure the app builds and runs
|
|
2. **Run lint checks**: `./gradlew lint`
|
|
3. **Update documentation**: If you changed APIs or features
|
|
4. **Add tests**: For new features or bug fixes
|
|
5. **Update CHANGELOG**: Add your changes to the unreleased section
|
|
|
|
### Submitting a Pull Request
|
|
|
|
1. **Push your branch**:
|
|
```bash
|
|
git push origin feature/your-feature-name
|
|
```
|
|
|
|
2. **Create Pull Request** on GitHub with:
|
|
- Clear title describing the change
|
|
- Detailed description of what and why
|
|
- Link to related issues
|
|
- Screenshots/recordings for UI changes
|
|
- Test instructions
|
|
|
|
3. **PR Template**:
|
|
```markdown
|
|
## Description
|
|
Brief description of changes.
|
|
|
|
## Type of Change
|
|
- [ ] Bug fix
|
|
- [ ] New feature
|
|
- [ ] Breaking change
|
|
- [ ] Documentation update
|
|
|
|
## Related Issues
|
|
Closes #123
|
|
|
|
## Testing
|
|
- [ ] Tested on physical device
|
|
- [ ] Tested on emulator
|
|
- [ ] Added unit tests
|
|
- [ ] Added UI tests
|
|
|
|
## Screenshots
|
|
[Add screenshots if applicable]
|
|
|
|
## Checklist
|
|
- [ ] Code follows style guidelines
|
|
- [ ] Self-reviewed the code
|
|
- [ ] Commented complex code
|
|
- [ ] Updated documentation
|
|
- [ ] No new warnings
|
|
- [ ] Added tests
|
|
- [ ] All tests pass
|
|
```
|
|
|
|
### Review Process
|
|
|
|
1. Maintainer will review your PR
|
|
2. Address any requested changes
|
|
3. Once approved, your PR will be merged
|
|
4. Delete your branch after merge
|
|
|
|
## Testing
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
# Run all tests
|
|
./gradlew test
|
|
|
|
# Run unit tests
|
|
./gradlew testDebugUnitTest
|
|
|
|
# Run instrumented tests
|
|
./gradlew connectedAndroidTest
|
|
```
|
|
|
|
### Writing Tests
|
|
|
|
#### Unit Tests
|
|
|
|
```kotlin
|
|
class TimelineViewModelTest {
|
|
@Test
|
|
fun `loadTimeline updates state to Success on successful fetch`() = runTest {
|
|
// Arrange
|
|
val mockRepository = mock<MastodonRepository>()
|
|
val testStatuses = listOf(/* test data */)
|
|
whenever(mockRepository.getPublicTimeline())
|
|
.thenReturn(Result.success(testStatuses))
|
|
|
|
val viewModel = TimelineViewModel(mockRepository)
|
|
|
|
// Act
|
|
viewModel.loadTimeline()
|
|
|
|
// Assert
|
|
val state = viewModel.uiState.value
|
|
assertTrue(state is TimelineUiState.Success)
|
|
assertEquals(testStatuses, (state as TimelineUiState.Success).statuses)
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Compose UI Tests
|
|
|
|
```kotlin
|
|
class StatusCardTest {
|
|
@get:Rule
|
|
val composeTestRule = createComposeRule()
|
|
|
|
@Test
|
|
fun statusCard_displays_username() {
|
|
val testStatus = Status(/* test data */)
|
|
|
|
composeTestRule.setContent {
|
|
StatusCard(status = testStatus)
|
|
}
|
|
|
|
composeTestRule
|
|
.onNodeWithText(testStatus.account.username)
|
|
.assertIsDisplayed()
|
|
}
|
|
}
|
|
```
|
|
|
|
## Documentation
|
|
|
|
### Code Documentation
|
|
|
|
- Add KDoc comments for all public APIs
|
|
- Comment complex algorithms
|
|
- Use meaningful variable and function names
|
|
- Update README.md for user-facing changes
|
|
|
|
### Documentation Files
|
|
|
|
- **README.md**: User documentation, setup, features
|
|
- **ARCHITECTURE.md**: Architecture and design decisions
|
|
- **API.md**: API integration details
|
|
- **CONTRIBUTING.md**: This file
|
|
|
|
## Questions?
|
|
|
|
If you have questions:
|
|
1. Check existing documentation
|
|
2. Search closed issues
|
|
3. Ask in discussions
|
|
4. Open a new issue with the `question` label
|
|
|
|
## Recognition
|
|
|
|
Contributors will be recognized in:
|
|
- CONTRIBUTORS.md file
|
|
- Release notes
|
|
- Project README
|
|
|
|
Thank you for contributing to My ActivityPub! 🎉
|