-
Notifications
You must be signed in to change notification settings - Fork 0
Contributing Guide
Panduan lengkap untuk berkontribusi pada Local YouTube Downloader Android project.
Terima kasih atas minat Anda untuk berkontribusi! Project ini terbuka untuk semua jenis kontribusi, mulai dari bug reports, feature requests, documentation improvements, hingga code contributions.
- Getting Started
- Types of Contributions
- Development Setup
- Code Guidelines
- Pull Request Process
- Issue Guidelines
- Community Guidelines
Sebelum berkontribusi, pastikan Anda memiliki:
- GitHub account untuk fork dan pull requests
- Android Studio Flamingo atau lebih baru
- Git untuk version control
- Basic knowledge of Kotlin dan Android development
- β Star the repository jika Anda menyukai project ini
- π΄ Fork the repository ke akun GitHub Anda
- π Read the documentation untuk memahami project
- π Browse existing issues untuk melihat apa yang bisa dikerjakan
Laporkan bugs yang Anda temukan dengan informasi detail.
What makes a good bug report:
- Clear, descriptive title
- Steps to reproduce
- Expected vs actual behavior
- Device/OS information
- Screenshots/logs if applicable
Usulkan fitur baru yang akan meningkatkan aplikasi.
What makes a good feature request:
- Clear problem statement
- Proposed solution
- Use cases and benefits
- Mockups/wireframes (optional)
Improve documentation, tutorials, atau wiki pages.
Documentation contributions:
- Fix typos or unclear explanations
- Add missing documentation
- Create tutorials or guides
- Translate documentation
Contribute code untuk bug fixes, new features, atau improvements.
Code contribution areas:
- Bug fixes
- New features
- Performance improvements
- UI/UX enhancements
- Test coverage
- Refactoring
Help improve test coverage dan quality assurance.
Testing contributions:
- Write unit tests
- Create integration tests
- Manual testing on different devices
- Performance testing
# Fork repository di GitHub, kemudian clone
git clone https://github.com/YOUR_USERNAME/Local-Youtube-Downloader-Android.git
cd Local-Youtube-Downloader-Android
# Add upstream remote
git remote add upstream https://github.com/ORIGINAL_OWNER/Local-Youtube-Downloader-Android.git# Open project di Android Studio
# Atau via command line:
./gradlew build
# Run tests
./gradlew test
./gradlew connectedAndroidTest# Update main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/your-feature-name
# atau
git checkout -b bugfix/issue-number-description- Follow Code Guidelines
- Write tests for new functionality
- Update documentation if needed
- Test your changes thoroughly
# Stage changes
git add .
# Commit with descriptive message
git commit -m "feat: add video quality selection feature"
# Push to your fork
git push origin feature/your-feature-nameFollow Kotlin Coding Conventions:
// β
Good
class DownloadRepository(private val context: Context) {
suspend fun getVideoInfo(url: String): Result<VideoInfo> {
return try {
// Implementation
Result.success(videoInfo)
} catch (e: Exception) {
Result.failure(e)
}
}
}
// β Bad
class downloadRepository(context:Context){
suspend fun getVideoInfo(url:String):Result<VideoInfo>{
try{
// Implementation
return Result.success(videoInfo)
}catch(e:Exception){
return Result.failure(e)
}
}
}// β
Good - Proper separation of concerns
class DownloadViewModel : ViewModel() {
private val repository = DownloadRepository()
private val _uiState = MutableStateFlow(DownloadUiState())
val uiState: StateFlow<DownloadUiState> = _uiState.asStateFlow()
fun startDownload() {
viewModelScope.launch {
repository.downloadVideo(request).collect { state ->
_downloadState.value = state
}
}
}
}// β
Good - Stateless composable
@Composable
fun VideoInfoCard(
videoInfo: VideoInfo,
onDownload: () -> Unit,
modifier: Modifier = Modifier
) {
Card(modifier = modifier) {
// UI implementation
}
}
// β Bad - Stateful composable with business logic
@Composable
fun VideoInfoCard(url: String) {
var videoInfo by remember { mutableStateOf<VideoInfo?>(null) }
LaunchedEffect(url) {
// Don't do business logic in composables
videoInfo = repository.getVideoInfo(url)
}
}// β
Good
class DownloadRepository
class YouTubeExtractorService
class DownloadViewModel
// β Bad
class downloadRepo
class youtubeService
class VM// β
Good
fun getVideoInfo()
fun startDownload()
fun validateUrl()
// β Bad
fun getInfo()
fun start()
fun validate()// β
Good
val downloadState: StateFlow<DownloadState>
val videoInfo: VideoInfo?
val isLoading: Boolean
// β Bad
val state: StateFlow<DownloadState>
val info: VideoInfo?
val loading: Boolean// β
Good - Use Result type for operations that can fail
suspend fun getVideoInfo(url: String): Result<VideoInfo> {
return try {
val info = youtubeExtractor.extractVideoInfo(url)
Result.success(info)
} catch (e: Exception) {
Result.failure(AppError.NetworkError("Failed to get video info: ${e.message}"))
}
}
// β
Good - Handle errors gracefully in UI
when (val result = repository.getVideoInfo(url)) {
is Result.Success -> {
_uiState.value = _uiState.value.copy(
videoInfo = result.data,
isLoading = false
)
}
is Result.Failure -> {
_uiState.value = _uiState.value.copy(
errorMessage = result.error.message,
isLoading = false
)
}
}class DownloadRepositoryTest {
@Test
fun `getVideoInfo returns success for valid URL`() = runTest {
// Given
val repository = DownloadRepository(mockContext)
val validUrl = "https://youtube.com/watch?v=dQw4w9WgXcQ"
// When
val result = repository.getVideoInfo(validUrl)
// Then
assertTrue(result.isSuccess)
assertNotNull(result.getOrNull())
}
@Test
fun `getVideoInfo returns failure for invalid URL`() = runTest {
// Given
val repository = DownloadRepository(mockContext)
val invalidUrl = "invalid-url"
// When
val result = repository.getVideoInfo(invalidUrl)
// Then
assertTrue(result.isFailure)
}
}@RunWith(AndroidJUnit4::class)
class DownloadIntegrationTest {
@Test
fun downloadFlow_completesSuccessfully() {
// Test complete download flow
val scenario = launchActivity<MainActivity>()
onView(withId(R.id.url_input))
.perform(typeText("https://youtube.com/watch?v=dQw4w9WgXcQ"))
onView(withId(R.id.download_button))
.perform(click())
// Verify download completes
onView(withText("Download selesai"))
.check(matches(isDisplayed()))
}
}- Code follows style guidelines
- Tests pass locally (
./gradlew test) - New functionality has tests
- Documentation updated if needed
- No merge conflicts with main branch
- Commit messages are descriptive
- Push your branch to your fork
-
Create PR from your branch to
mainbranch - Fill PR template with required information
- Link related issues using keywords (fixes #123)
## Description
Brief description of changes made.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
## Screenshots (if applicable)
Add screenshots to help explain your changes.
## Checklist
- [ ] My code follows the style guidelines
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works- Automated checks run (CI/CD)
- Code review by maintainers
- Address feedback if requested
- Approval and merge by maintainers
# Update your local main branch
git checkout main
git pull upstream main
# Delete feature branch
git branch -d feature/your-feature-name
git push origin --delete feature/your-feature-name**Bug Description**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Device Information:**
- Device: [e.g. Samsung Galaxy S21]
- OS: [e.g. Android 12]
- App Version: [e.g. 1.0.0]
**Additional Context**
Add any other context about the problem here.**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.-
bug- Something isn't working -
enhancement- New feature or request -
documentation- Improvements or additions to documentation -
good first issue- Good for newcomers -
help wanted- Extra attention is needed -
question- Further information is requested -
wontfix- This will not be worked on
-
priority: high- Critical issues -
priority: medium- Important issues -
priority: low- Nice to have
-
status: in progress- Currently being worked on -
status: needs review- Waiting for review -
status: blocked- Blocked by other issues
We follow the Contributor Covenant Code of Conduct:
- Be welcoming and inclusive
- Be respectful of differing viewpoints
- Accept constructive criticism gracefully
- Focus on what is best for the community
Examples of behavior that contributes to a positive environment:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior:
- The use of sexualized language or imagery
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Search existing issues before creating new ones
- Use clear, descriptive titles
- Provide detailed information in issue descriptions
- Be patient - maintainers are volunteers
- Be respectful in all interactions
- Keep PRs focused - one feature/fix per PR
- Write clear commit messages
- Respond to feedback constructively
- Be patient during review process
- Stay on topic in discussions
- Help other contributors when possible
- Share knowledge and experiences
- Be constructive in feedback
All contributors are recognized in:
- README.md contributors section
- Release notes for significant contributions
- GitHub contributors page
- Code contributors - Direct code contributions
- Documentation contributors - Documentation improvements
- Community contributors - Helping others, reporting bugs
- Design contributors - UI/UX improvements
- GitHub Discussions - General questions and discussions
- GitHub Issues - Bug reports and feature requests
- Wiki - Documentation and guides
New contributors can get help from:
- Good first issues - Labeled for beginners
- Maintainer guidance - Ask questions in issues/PRs
- Community support - Other contributors helping
After reading this guide:
- Set up development environment
- Look for "good first issue" labels
- Join GitHub Discussions
- Start with small contributions
- Ask questions when needed
Thank you for contributing! π Your contributions make this project better for everyone.
Questions? Feel free to ask in GitHub Discussions or create an issue.