EAPlayers is a Kotlin Multiplatform project utilizing Compose Multiplatform to deliver a native app experience for Android, iOS, and desktop.
Android | iOS | Desktop |
---|---|---|
EAPlayers is a showcase of the latest Kotlin Multiplatform technologies for mobile development using a fully Compose-based UI framework for both Android and iOS. Key features include:
- 🧩 Shared ViewModels for business logic across platforms
- 🖼️ Compose Multiplatform-based UI, allowing the views to be shared across Android and iOS for a consistent user experience
- 🧳 Shared navigation implementation using Compose Multiplatform, enabling a unified navigation experience on both platforms
- 🖥️ Compose for Desktop support
- 🏗️ Multi-modular architecture for improved maintainability, scalability, and build efficiency
- 📡 Fetching player details and team information from EA's Drop API
- 🚦 Detekt for static code analysis and maintaining code quality
- 🛠️ Code Style and Inspections to enforce consistent formatting and static analysis
- ⚙️ GitHub Actions for continuous integration to ensure code quality
- 🌙 Dark mode support for both platforms
- 🧪 Unit Tests for ViewModels and UseCases to ensure business logic correctness
- 💉 Koin - Dependency injection
- 🌎 Ktor - Network communication
- 📦 Coil - Image loading
- 📋 Kermit - Logging
- 🧹 Mockk - A powerful mocking library for Kotlin unit tests.
- 📊 Kover for test coverage tracking, ensuring high code quality with coverage reports.
- Android Studio Ladybug | 2024.2.1 Patch 1
- Xcode: Version 16.0
Unit Tests
The project includes unit tests for critical business logic components like ViewModels and UseCases. These tests run on Android, ensuring the robustness of the core logic across platforms. The tests are written using Kotlin's built-in testing framework, with mocking provided by Mockk to simplify testing dependencies.
- ViewModel Tests: Verifying the business logic and states generated in the shared ViewModel.
- Service (UseCase) Tests: Ensuring correctness of the app's core operations, including fetching player and team data.
- Mocking: Uses Mockk to mock dependencies in ViewModels and UseCases for isolated testing.
- Code Coverage: For newly added ViewModels and Services, Kover ensures that they meet a minimum of 80% code coverage.
To check the code coverage for the project, run:
./gradlew koverHtmlReportDebug
This will generate a detailed HTML report of the code coverage at the following location:
./composeApp/build/reports/kover/htmlDebug/index.html
To verify that the code meets the required minimum 80% code coverage, use the following command:
./gradlew koverVerifyDebug
This command will ensure that the coverage verification passes, enforcing the code quality standards for the project.
Setting up Code Style and Inspections in IDEA / Android Studio
- Import code style: Android Studio -> Settings -> Editor -> Code style.
- At the Scheme section click the settings gear
- Choose Import scheme...
- Browse the code style config file at ./config/codestyle.xml
- Hit Apply. You can now use Reformat code that complies to the standards.
- Import inspections: Android Studio -> Settings -> Editor -> Inspections.
- At the Profile section click the settings gear
- Choose Import profile...
- Browse the inspections config file at ./config/inspections.xml
- Hit Apply.
Desktop Support
The project includes desktop support using Compose for Desktop. This allows the application to run natively, providing a consistent user experience across mobile and desktop environments.
To run the desktop version of the app, follow these steps:
-
Ensure you have the necessary environment set up, including a compatible JDK and Kotlin Multiplatform dependencies.
-
Use the following command to build and run the desktop application:
./gradlew composeApp:run
-
The application will start up and can be tested on your local machine.
Detekt
- 🚦 The project uses Detekt for static code analysis and formatting.
- Detekt helps maintain code quality by identifying potential issues in the codebase.
- To run Detekt, use the following command:
./gradlew detekt
Theming
The app implements a custom theme system to support dynamic theming and dark mode. The theme includes dimensions, colors, typography, shapes, and ripple effects, all of which can adapt to the current system theme (light or dark). The AppTheme
composable allows you to toggle between light and dark themes and provides a MaterialTheme
wrapper to ensure consistent appearance throughout the app.
The color scheme is dynamically generated based on the current theme settings, and additional customization can be applied using local providers for text selection colors, ripple effects, and typography. This ensures a cohesive look and feel while leveraging the power of Compose's Material 3 design.
Multi-modular Architecture
The project follows a multi-modular architecture to enhance scalability, maintainability, and build efficiency. The modularization approach is as follows:
-
Features Module: The app's features are divided into separate modules like
details
andlist
, each containing aview
for the UI and aviewmodel
for the presentation logic. This helps isolate individual features and facilitates independent development and testing. -
Core Module: Houses core utilities and extensions used throughout the app.
-
Data Module: Manages data sources, repositories, and API interactions. It serves as a centralized module for managing data flow.
-
DI Module: Contains the dependency injection setup using Koin to provide a modular and easily configurable DI configuration.
-
Domain Module: Encapsulates the business logic and use cases of the application, separating it from the data handling and UI layers.
-
Logger Module: Implements logging functionalities using Kermit, enabling consistent logging across the entire codebase.
-
Navigation Module: Manages navigation logic for both Android and iOS, making it easier to handle cross-platform navigation requirements.
-
Theme Module: Contains all theming-related resources, such as color schemes, typography, dimensions, and shape configurations, for a consistent visual experience.
The multi-modular structure helps in isolating functionalities, making the codebase more manageable, and accelerating build times by reducing the impact of changes on other parts of the project.
Dependency Management
The project uses Renovate for automated dependency updates. Renovate helps keep dependencies up-to-date by regularly checking for new versions and creating pull requests for updates.
The configuration file for Renovate is located in the root of the project: renovate.json.
Contributing
Contributions are welcome! Here’s the process for contributing to EAPlayers:
-
Check the issues section on the repository. There are various issues listed that need help.
-
To work on an issue, create a new branch from the
development
branch named after the corresponding issue. -
Once you have a solution, run the
./gradlew build
command locally to ensure that the build is successful. -
If the build passes, create a pull request targeting the
development
branch. Make sure to assign the pull request to @kaszabimre for approval. -
Once the pull request is approved, the solution will be considered successfully integrated.
Commit Message Conventions
The project follows the Conventional Commits standard for commit messages. This convention is important for maintaining consistent commit history and will be utilized in the future for generating release logs.
Please ensure that your commit messages adhere to the specified format to facilitate automated release note generation.
GitHub Actions
The project utilizes GitHub Actions for continuous integration (CI) to ensure code quality and maintainability. The primary workflow is defined as a "PR job," which is triggered on the following events:
- Manual trigger (
workflow_dispatch
) - Pushes to the
main
ordevelopment
branches - Pull requests, excluding changes to markdown files, images, and documentation
The workflow consists of several jobs:
-
Pre-conditions:
- Sets up the environment by checking out the repository, configuring the JDK (Java 18), caching Kotlin Multiplatform dependencies, running
detekt
for static code analysis, and executing SwiftLint for iOS-specific code.
- Sets up the environment by checking out the repository, configuring the JDK (Java 18), caching Kotlin Multiplatform dependencies, running
-
Build Android:
- Depends on the "pre-conditions" job.
- Involves setting up the environment and building the Android project using Gradle.
-
Build iOS:
- Depends on the "pre-conditions" job.
- Configures the environment, selects the Xcode version, resolves Swift package dependencies, and builds the iOS app using
xcodebuild
. It targets an iOS Simulator with the specified configuration.
-
Comment Test:
- Depends on the "pre-conditions" job.
- Adds the Kover report to the pull request if the build passes.
A custom action is used for caching Gradle and Kotlin Native artifacts to speed up the build process. The action caches directories such as Gradle caches, wrapper files, and Kotlin Native dependencies. The cache keys are based on the content of Gradle build files, ensuring cache consistency across builds.
This workflow downloads a code coverage report artifact and adds it as a comment to the pull request using the Kover Report GitHub Action.
This workflow runs the koverXmlReportDebug Gradle task and generates an XML report for code coverage using the Kover plugin.