Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .cursor/rules/android/android_clean_architecture.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: Enforce clean architecture principles in Android projects
globs:
- "app/src/main/java/**"
alwaysApply: true
---
- Follow domain/data/presentation separation: domain is business logic, data is data sources, presentation is UI.
- Keep domain layer free of Android framework dependencies.
- Use UseCases (Interactors) for business rules, triggered from ViewModels or Controllers.
- Repositories should expose interfaces, not implementations.
- Avoid directly accessing data sources in presentation layer.
- Prefer dependency inversion: inject interfaces rather than concrete classes.
- Maintain simple, testable domain models.
13 changes: 13 additions & 0 deletions .cursor/rules/android/android_di_hilt_patterns.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: Dependency injection patterns with Hilt
globs:
- "app/src/main/java/**"
alwaysApply: true
---
- Annotate Application class with @HiltAndroidApp
- Use @HiltViewModel for ViewModel injection
- Provide dependencies in @Module with @InstallIn
- Inject interfaces rather than concrete implementations
- Use qualifiers when multiple implementations exist
- Avoid static singletons outside of Hilt’s graph
- Keep modules small and logically grouped
38 changes: 38 additions & 0 deletions .cursor/rules/android/android_general_rules.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
alwaysApply: false
---
For every Kotlin Android code you generate or refactor:

1. **Architecture:**
- Follow **MVVM pattern** strictly.
- Business logic must go into `ViewModel`, not in `View` (Activity/Fragment/Composable).
- Views should only observe `StateFlow`/`LiveData` from ViewModel.

2. **Kotlin Best Practices:**
- Use `StateFlow` instead of `LiveData` unless explicitly required.
- Use Kotlin Coroutines (structured concurrency, `viewModelScope`, `SupervisorJob`).
- Prefer `val` over `var` where possible.
- Use extension functions and sealed classes when appropriate.
- No memory leaks (avoid context leaks in ViewModel).
- Use Dependency Injection (Hilt) if necessary.

3. **Android Performance:**
- Avoid heavy work on the main thread.
- Use `Dispatchers.IO` or background coroutines for I/O, disk, and network tasks.
- Use `lazy` initialization where suitable.
- For RecyclerView/List: use `ListAdapter` + `DiffUtil`.
- Avoid unnecessary recomposition in Jetpack Compose.
- Apply LRU caching for repeated data/images if needed.

4. **Testing:**
- Generated ViewModel and Repository code must be testable (no static singletons).
- Show sample unit test if introducing new logic.

5. **Code Quality:**
- Minimize code duplication.
- Clear function separation (Single Responsibility Principle).
- Provide brief inline comments for complex sections.

6. **Output Requirement:**
- Provide **full code samples** (including imports) unless specified otherwise.
- Brief explanation of key design decisions made.
11 changes: 11 additions & 0 deletions .cursor/rules/android/android_integration_testing.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Android Integration Testing best practices for multi-layer testing
alwaysApply: false
---
- Integration tests should verify interactions between multiple layers (e.g., ViewModel + Repository + Data Source).
- Use **Hilt Test Components** or DI overrides to inject fake or in-memory dependencies.
- Avoid hitting real external services; use mocked network responses or test databases.
- Write integration tests to cover critical user flows end-to-end.
- Keep tests stable and repeatable; clean up any test data after execution.
- Use **JUnit Rules** or **TestContainers** where applicable for environment setup/teardown.
- Separate integration tests from unit tests and run them less frequently (e.g., nightly builds).
13 changes: 13 additions & 0 deletions .cursor/rules/android/android_naming_conventions.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: Naming conventions for consistency
globs:
- "**/*.kt"
alwaysApply: true
---
- Classes: PascalCase
- Functions: camelCase
- Constants: UPPER_SNAKE_CASE
- Variables: camelCase
- Test functions: GIVEN_<condition> WHEN <action> THEN <result>
- Avoid abbreviations and cryptic names
- Name should communicate clear intent
11 changes: 11 additions & 0 deletions .cursor/rules/android/android_ui_testing.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Android UI testing best practices using Espresso and Compose Testing
alwaysApply: false
---
- Use **Espresso** for testing classic Android Views; use **Compose Testing APIs** for Jetpack Compose UI.
- Keep UI tests focused on user interactions and visible UI changes.
- Avoid complex logic in UI tests; delegate business logic testing to unit tests.
- Use **Idling Resources** or `composeTestRule.awaitIdle()` to synchronize asynchronous events.
- Use clear, descriptive test names that reflect user behavior being tested.
- Isolate UI tests from backend dependencies by using mock servers or test doubles.
- Run UI tests on real or emulated devices to catch platform-specific issues.
24 changes: 24 additions & 0 deletions .cursor/rules/android/android_unit_testing_bdd.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
description: Unit testing best practices with BDD style
alwaysApply: false
---
- Name test functions in BDD style: given_<condition>_when_<action>_then_<result>
- Use GIVEN, WHEN, THEN comments in the test body for clarity.
- Write one behavioral scenario per test.
- Use mocks (MockK, Mockito) to isolate dependencies.
- Prefer runTest or coroutine test rules for suspend functions.
- Avoid fragile tests with real-time delays or random input.
- Example:
```kotlin
@Test
fun givenValidUser_whenFetchUser_thenReturnsUser() {
// GIVEN
val userId = 123
coEvery { userRepo.getUser(userId) } returns User(userId, "Alice")

// WHEN
val result = runBlocking { sut.fetchUser(userId) }

// THEN
assertEquals("Alice", result.name)
}
11 changes: 11 additions & 0 deletions .cursor/rules/android/android_workmanager_best_practices.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Best practices for WorkManager usage in background tasks
alwaysApply: false
---
- Use `CoroutineWorker` for suspendable background work.
- Keep work inputs and outputs small and serializable.
- Chain dependent work using `WorkContinuation`.
- Use appropriate `Constraints` for battery and network considerations.
- Monitor and handle work statuses for retries and failures gracefully.
- Avoid long-running tasks; break them into smaller units if needed.
- Clean up or cancel obsolete work to prevent resource leaks.
12 changes: 12 additions & 0 deletions .cursor/rules/general_clean_code_principles.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: Clean code principles for better readability
alwaysApply: false
---
- Keep functions small and focused
- One class per file
- Limit function size to 20 lines if possible
- Avoid long parameter lists (max 3–4 parameters)
- Minimize nested control structures
- Remove commented-out code before committing
- Prefer meaningful names over comments
- DRY (Don’t Repeat Yourself): extract duplication
11 changes: 11 additions & 0 deletions .cursor/rules/general_performance_tips.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Performance best practices for Android
alwaysApply: false
---
- Avoid allocating objects in tight loops
- Use lazy initialization where appropriate
- Reuse existing objects instead of recreating
- Prefer immutable data structures for concurrency
- Minimize reflection usage
- Avoid excessive recomposition in Compose by using keys and remember
- Profile and measure before optimizing prematurely
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
root = true

[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8

[*.{kt,kts}]
indent_size = 4
indent_style = space
max_line_length = 100
ktlint_standard_max_line_length = 100
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
ktlint_standard_no-wildcard-imports = disabled
1 change: 0 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ android {

namespace 'com.nphausg.app.embeddedserver'

compileSdk 34
compileSdk 35

defaultConfig {
applicationId "com.nphausg.app.embeddedserver"
minSdk 21
targetSdk 34
targetSdk 35
versionCode 1
versionName "1.0.0"

Expand Down
16 changes: 8 additions & 8 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
agp = "8.5.2"
appcompat = "1.7.0"
coreSplashscreen = "1.0.1"
gradle = "8.8.0"
kotlin = "1.9.0"
coreKtx = "1.13.1"
gradle = "8.9.1"
kotlin = "2.0.21"
coreKtx = "1.16.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
Expand All @@ -20,12 +20,12 @@ ktorServerCore = "2.3.12"
ktorServerCors = "2.3.10"
ktorClientContentNegotiation = "2.3.10"
ktorServerNetty = "2.3.10"
lifecycleRuntimeKtx = "2.8.5"
activityCompose = "1.9.2"
composeBom = "2024.09.00"
mockitoCore = "3.12.4"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.10.1"
composeBom = "2025.04.00"
mockitoCore = "5.15.2"
mockitoInline = "3.11.2"
navigationCompose = "2.8.0"
navigationCompose = "2.8.9"

[libraries]
# Kotlin
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Thu Oct 21 23:49:45 ICT 2021
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME