Skip to content

Commit

Permalink
Merge pull request #7 from alsterverse/feature/add-ui-state
Browse files Browse the repository at this point in the history
Add UI state
  • Loading branch information
Mats-Hjalmar authored Oct 19, 2024
2 parents 3f0e0ce + 9159549 commit ec20a0d
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 78 deletions.
87 changes: 10 additions & 77 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -4,103 +4,36 @@

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 {
implementation("se.alster:player:<version>")
}
```

## 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.
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ dependencyResolutionManagement {
}

rootProject.name = "alster-modules"
include(":player")
include(":player")
include(":ui-state")
60 changes: 60 additions & 0 deletions ui-state/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -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)
}
63 changes: 63 additions & 0 deletions ui-state/src/commonMain/kotlin/se/alster/ui_state/UiState.kt
Original file line number Diff line number Diff line change
@@ -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<out T> {
data object Idle : UiState<Nothing>
data object Loading : UiState<Nothing>
data class Data<out T>(val value: T) : UiState<T>
data class Error(val value: Throwable) : UiState<Nothing>
}

/**
* Converts a [Result] to a [UiState].
*/
fun <T> Result<T>.toUiState(): UiState<T> {
onSuccess {
return UiState.Data(it)
}
onFailure {
return UiState.Error(it)
}
return UiState.Loading
}

/**
* Converts a value to a [UiState.Data].
*/
fun <T : Any> T.toUiStateData(): UiState.Data<T> {
return UiState.Data(this)
}

/**
* Maps the data of a [UiState] to another type.
*/
fun <T, R> UiState<T>.mapData(data: (T) -> R): UiState<R> {
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 <T> UiState<T>.dataOrNull(): T? {
return when (this) {
is UiState.Data -> value
else -> null
}
}

0 comments on commit ec20a0d

Please sign in to comment.