A modern currency converter application built with Kotlin Multiplatform and Jetpack Compose, following Clean Architecture principles and MVI (Model-View-Intent) pattern. The app provides real-time currency conversion and historical rates for the last three days.
- Real-time currency conversion with latest exchange rates
- Historical exchange rates for the last three days
- Support for multiple currencies
- Offline support with cached exchange rates
- Clean and intuitive UI built with Compose Multiplatform
- Dark/Light theme support
- Cross-platform support (Android, iOS, Desktop)
The project follows Clean Architecture principles with MVI pattern:
├── app/
│ ├── core/
│ ├── currency/
│ │ ├── presentation/
│ │ ├── domain/
│ │ └── data/
│ ├── android/
│ ├── ios/
│ └── desktop/
- Multiplatform: Kotlin Multiplatform
- UI Framework: Jetpack Compose Multiplatform
- Architecture Pattern: MVI (Model-View-Intent)
- Dependency Injection: Koin
- Networking: Ktor
- Local Storage: SQLDelight
- Async Operations: Kotlin Coroutines & Flow
- Testing: KotlinTest, JUnit5
- CI/CD: GitHub Actions
- Implements MVI pattern
- ViewModels handle business logic
- UI States represent screen data
- Events handle user interactions
- Side effects manage one-time actions
- Contains business logic and rules
- Use cases orchestrate data flow
- Repository interfaces define data contracts
- Models represent business objects
- Implements repository interfaces
- Manages data sources (API/Local)
- Handles data caching
- Maps DTOs to domain models
Using Koin for dependency injection across all platforms:
val appModule = module {
single { CurrencyRepository(get(), get()) }
single { CurrencyDatabase(get()) }
viewModel { CurrencyViewModel(get(), get()) }
}
data class CurrencyState(
val currencies: List<Currency> = emptyList(),
val fromCurrency: Currency? = null,
val toCurrency: Currency? = null,
val amount: String = "",
val convertedAmount: String = "",
val historicalRates: List<HistoricalRate> = emptyList(),
val isLoading: Boolean = false,
val error: String? = null
)
sealed class CurrencyEvent {
data class SelectFromCurrency(val currency: Currency) : CurrencyEvent()
data class SelectToCurrency(val currency: Currency) : CurrencyEvent()
data class AmountChanged(val amount: String) : CurrencyEvent()
object SwapCurrencies : CurrencyEvent()
object RefreshRates : CurrencyEvent()
}
sealed class CurrencyEffect {
data class ShowError(val message: String) : CurrencyEffect()
object NavigateToSettings : CurrencyEffect()
}
- Android Studio Arctic Fox or later
- Xcode 13 or later (for iOS)
- JDK 11 or later
- Kotlin Multiplatform Mobile plugin
- Clone the repository:
git clone https://github.com/yourusername/currency-converter.git
-
Open the project in Android Studio
-
Add your API key in
local.properties
:
CURRENCY_API_KEY=your_api_key_here
- Build and run the project
The project includes:
- Unit tests for business logic
- Integration tests for repositories
- UI tests for components
- End-to-end tests for critical flows
Run tests:
./gradlew test
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details
- Exchange Rate API for currency data
- Compose Multiplatform for UI framework
- Kotlin Multiplatform for cross-platform development