Contributing to CameraK¶
Thank you for your interest in contributing to CameraK! This document provides guidelines and steps for contributing.
Ways to Contribute¶
- 🐛 Report Bugs — Found an issue? Let us know
- 💡 Suggest Features — Have an idea? Share it
- 📖 Improve Documentation — Fix typos, add examples, clarify
- 🔧 Submit Pull Requests — Fix bugs, add features
- 💬 Help Others — Answer questions in Discussions
Reporting Issues¶
Before creating an issue, please:
- Search existing issues to avoid duplicates
- Use the issue template if available
- Provide details:
- CameraK version
- Platform (Android/iOS/Desktop) and OS version
- Device/emulator details
- Minimal reproducible example
- Expected vs actual behavior
- Stack trace/error messages
Good Issue Example¶
**CameraK Version:** 0.2.0
**Platform:** Android 13 (Pixel 6)
**Description:**
Camera preview shows black screen when using RATIO_1_1 aspect ratio.
**Steps to Reproduce:**
1. Configure camera with `setAspectRatio(AspectRatio.RATIO_1_1)`
2. Launch camera screen
3. Preview displays as black screen
**Expected:** Square camera preview displays
**Actual:** Black screen
**Code:**
```kotlin
val stateHolder = rememberCameraKState(
permissions = permissions,
cameraConfiguration = {
setAspectRatio(AspectRatio.RATIO_1_1)
}
)
Error Log:
E/CameraK: Failed to bind camera...
## Development Setup
### Prerequisites
- JDK 11+
- Android Studio Hedgehog or later
- Xcode 14+ (for iOS development)
- Kotlin 1.9.0+
### Clone Repository
```bash
git clone https://github.com/Kashif-E/CameraK.git
cd CameraK
Build Project¶
./gradlew build
Run Sample App¶
Android:
./gradlew :Sample:installDebug
Desktop:
./gradlew :Sample:run
iOS:
cd iosApp
pod install
open iosApp.xcworkspace
Code Guidelines¶
Kotlin Style¶
Follow Kotlin coding conventions:
- Use 4 spaces for indentation
- Use camelCase for functions and variables
- Use PascalCase for classes
- Maximum line length: 120 characters
Naming Conventions¶
Critical: Follow SDK naming rules
- Methods:
[Verb][Object]pattern - ✅
captureImage(),setZoom(),getFlashMode() -
❌
imageCapturer(),zoomSet(),flashModeGet() -
Classes: Singular nouns
- ✅
CameraController,ImageCaptureResult -
❌
Controllers,ImageCaptureResults -
Packages: Domain-based
- ✅
com.kashif.cameraK.controller - ❌
com.kashif.cameraK.utils
Documentation¶
All public APIs must have KDoc:
/**
* Captures an image and saves it directly to a file.
*
* This method is significantly faster than takePicture() as it:
* - Saves directly to disk without ByteArray conversion
* - Skips decode/encode cycles (2-3 seconds faster)
* - Avoids memory overhead from ByteArray processing
*
* @return ImageCaptureResult.SuccessWithFile containing the file path, or an error result
*
* @throws IOException if file cannot be written
*
* @example
* ```kotlin
* when (val result = controller.takePictureToFile()) {
* is ImageCaptureResult.SuccessWithFile -> println("Saved: ${result.filePath}")
* is ImageCaptureResult.Error -> println("Error: ${result.exception.message}")
* }
* ```
*/
suspend fun takePictureToFile(): ImageCaptureResult
Error Handling¶
Use sealed classes for expected errors:
sealed class ImageCaptureResult {
data class SuccessWithFile(val filePath: String) : ImageCaptureResult()
data class Error(val exception: Exception) : ImageCaptureResult()
}
Use specific exceptions for unexpected errors:
class CameraNotInitializedException(message: String) : Exception(message)
Testing¶
Add tests for new features:
@Test
fun `takePictureToFile returns success with file path`() = runTest {
val controller = createTestController()
val result = controller.takePictureToFile()
assertTrue(result is ImageCaptureResult.SuccessWithFile)
assertNotNull((result as ImageCaptureResult.SuccessWithFile).filePath)
}
Pull Request Process¶
1. Fork and Branch¶
git checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fix
2. Make Changes¶
- Write clear, focused commits
- Follow code guidelines
- Add tests for new features
- Update documentation
3. Commit Messages¶
Use conventional commits:
feat: add pinch-to-zoom gesture support
fix: resolve camera preview freeze on rotation
docs: update installation guide for iOS
test: add zoom control unit tests
refactor: simplify flash mode toggle logic
4. Push and Create PR¶
git push origin feature/your-feature-name
Create pull request on GitHub with:
- Title: Clear, concise description
- Description:
- What changed
- Why (reference issue if applicable)
- How to test
- Screenshots/videos if UI change
- Checklist:
- [ ] Code follows style guidelines
- [ ] Documentation updated
- [ ] Tests added/updated
- [ ] All tests pass
- [ ] No breaking changes (or documented)
5. Code Review¶
- Address reviewer feedback
- Keep discussion respectful
- Update PR as needed
6. Merge¶
Once approved, maintainers will merge your PR.
Architecture Guidelines¶
Layer 1: Platform-Specific (expect/actual)¶
// commonMain
expect class CameraController {
suspend fun takePictureToFile(): ImageCaptureResult
}
// androidMain
actual class CameraController {
actual suspend fun takePictureToFile(): ImageCaptureResult {
// Android-specific CameraX implementation
}
}
Layer 2: State Management¶
@Stable
class CameraKStateHolder(
private val controllerFactory: suspend () -> CameraController,
private val coroutineScope: CoroutineScope
) {
val cameraState: StateFlow<CameraKState>
val uiState: StateFlow<CameraUIState>
}
Layer 3: Compose UI¶
@Composable
fun rememberCameraKState(...): CameraKStateHolder
Breaking Changes¶
Avoid breaking changes when possible. If necessary:
- Deprecate first (12-month timeline)
- Provide migration path
- Document in CHANGELOG
- Bump major version
@Deprecated(
message = "Use takePictureToFile() instead",
replaceWith = ReplaceWith("takePictureToFile()"),
level = DeprecationLevel.WARNING // v1.x
)
suspend fun takePicture(): ImageCaptureResult
Documentation Changes¶
Update documentation in docs/:
getting-started/— Installation, quick start, configurationguides/— Feature-specific guidesapi/— API referenceexamples/— Platform-specific examples
Use Stripe-style documentation: - Clear, concise examples - Real, working code - Copy-paste ready - Progressive disclosure (simple → advanced)
Community Guidelines¶
- Be respectful and inclusive
- Help others learn
- Provide constructive feedback
- Follow the Code of Conduct
Recognition¶
Contributors are recognized in: - GitHub contributors page - Release notes (for significant contributions) - CHANGELOG (for bug fixes and features)
Questions?¶
- GitHub Discussions: Discussions
- Issues: Issues
Thank You!¶
Your contributions make CameraK better for everyone. We appreciate your time and effort! 🙏