diff --git a/README.MD b/README.MD index a3bb0f8..15ced2f 100644 --- a/README.MD +++ b/README.MD @@ -4,96 +4,21 @@ Alster Player is a Kotlin Multiplatform project designed to provide a media player that works across Android and iOS platforms. The project leverages Kotlin Multiplatform Mobile (KMM) to share code between Android and iOS, while also using platform-specific APIs for media playback. -## Project Structure - -The project is structured as follows: - -- `commonMain`: Shared code between Android and iOS. -- `androidMain`: Android-specific code. -- `iosMain`: iOS-specific code. - -## Requirements - -- Android Studio Koala | 2024.1.1 -- Kotlin 1.8.0 or higher -- Gradle 7.0 or higher -- Xcode 13.0 or higher (for iOS development) - -## Setup - -### Clone the Repository - -```sh -git clone https://github.com/Alsterverse/alster-modules.git -cd alster-modules -``` - -### Configure GitHub Packages - -Create a `github.properties` file in the root directory with the following content: - -``` -gpr.user=YOUR_GITHUB_USERNAME -gpr.token=YOUR_GITHUB_TOKEN -``` - -### Open in Android Studio - -1. Open Android Studio. -2. Select "Open an existing project". -3. Navigate to the cloned repository and open it. - -## Usage - -### PlayerControllerIOS - -The `PlayerControllerIOS` class is responsible for managing the AVPlayer instance on iOS. It includes methods for loading, playing, pausing, and seeking within a video. - -### PlayerControllerAndroid - -The `PlayerControllerAndroid` class is responsible for managing the ExoPlayer instance on Android. It includes similar methods for loading, playing, pausing, and seeking within a video. - -## Dependencies - -### Common - -- `kotlinx.coroutines.core` - -### Android - -- `androidx.media3.exoplayer` -- `androidx.media3.exoplayer.hls` -- `androidx.media3.exoplayer.dash` - -### iOS - -- `AVFoundation` - -## Publishing - -The project is configured to publish to GitHub Packages. To publish a new version, run: - -```sh -./gradlew publish -``` - ## Installation To install a module from `Alster Modules`, follow these steps: -1. **Configure the `repositories` block in your `build.gradle.kts` file:** +1. **Configure the `repositories` block in your `settings.gradle.kts` file:** ```kotlin repositories { maven { url = uri("https://maven.pkg.github.com/Alsterverse/alster-modules") } - mavenCentral() - google() } ``` -2. **Add the dependency to the commonMain source set:** +2. **Add the dependency to the `commonMain` source set:** ```kotlin commonMain.dependencies { @@ -101,6 +26,14 @@ To install a module from `Alster Modules`, follow these steps: } ``` +## Publishing + +The project is configured to publish to GitHub Packages. To publish a new version, simply trigger a release in GitHub, and an action will create a new release. + +## Creating New Modules + +To create more modules, you can copy and paste an already existing module (e.g., `ui-state`) and include it in the project from `settings.gradle.kts`. + ## License This project is licensed under the MIT License. See the `LICENSE` file for details. diff --git a/settings.gradle.kts b/settings.gradle.kts index 2ed06f0..7ce9311 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,4 +15,5 @@ dependencyResolutionManagement { } rootProject.name = "alster-modules" -include(":player") \ No newline at end of file +include(":player") +include(":ui-state") \ No newline at end of file diff --git a/ui-state/build.gradle.kts b/ui-state/build.gradle.kts new file mode 100644 index 0000000..1562d7b --- /dev/null +++ b/ui-state/build.gradle.kts @@ -0,0 +1,60 @@ +import java.util.Properties + +val githubProperties = Properties().apply { + load(rootProject.file("github.properties").inputStream()) +} + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidLibrary) + id("com.vanniktech.maven.publish") +} + +val versionName = githubProperties.getProperty("version") + +kotlin { + androidTarget { + compilations.all { + kotlinOptions { + jvmTarget = "17" + } + } + publishLibraryVariants("release", "debug") + } + + iosX64() + iosArm64() + iosSimulatorArm64() + + jvmToolchain(17) + + sourceSets { + + } +} + +android { + namespace = "se.alster.ui_state" + compileSdk = 34 + defaultConfig { + minSdk = 24 + } +} + + +publishing { + repositories { + maven { + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/Alsterverse/alster-modules") + credentials { + username = githubProperties.getProperty("gpr.user") + password = githubProperties.getProperty("gpr.token") + } + } + } +} + +mavenPublishing { + coordinates("se.alster", "ui-state", versionName) +} \ No newline at end of file diff --git a/ui-state/src/commonMain/kotlin/se/alster/ui_state/UiState.kt b/ui-state/src/commonMain/kotlin/se/alster/ui_state/UiState.kt new file mode 100644 index 0000000..5e8402a --- /dev/null +++ b/ui-state/src/commonMain/kotlin/se/alster/ui_state/UiState.kt @@ -0,0 +1,63 @@ +package se.alster.ui_state + +/** + * Represents the state of a UI component. It can be in one of the following states: + * - [Idle] - The initial state of the UI component. + * - [Loading] - The UI component is loading data. + * - [Data] - The UI component has received data. + * - [Error] - An error occurred while loading data. + * @param T The type of the data. + * @see Result + * @see toUiState + * @see toUiStateData + * @see mapData + * @see dataOrNull + */ +sealed interface UiState { + data object Idle : UiState + data object Loading : UiState + data class Data(val value: T) : UiState + data class Error(val value: Throwable) : UiState +} + +/** + * Converts a [Result] to a [UiState]. + */ +fun Result.toUiState(): UiState { + onSuccess { + return UiState.Data(it) + } + onFailure { + return UiState.Error(it) + } + return UiState.Loading +} + +/** + * Converts a value to a [UiState.Data]. + */ +fun T.toUiStateData(): UiState.Data { + return UiState.Data(this) +} + +/** + * Maps the data of a [UiState] to another type. + */ +fun UiState.mapData(data: (T) -> R): UiState { + return when (this) { + is UiState.Data -> UiState.Data(data(value)) + is UiState.Error -> UiState.Error(value) + is UiState.Loading -> UiState.Loading + is UiState.Idle -> UiState.Idle + } +} + +/** + * Returns the data of a [UiState] or `null` if the state is not [UiState.Data]. + */ +fun UiState.dataOrNull(): T? { + return when (this) { + is UiState.Data -> value + else -> null + } +}