Kamel

Kotlin Asynchronous Media Loading Library that supports Compose

License

License

Categories

Categories

Data
GroupId

GroupId

com.alialbaali.kamel
ArtifactId

ArtifactId

kamel-core-metadata
Last Version

Last Version

0.2.0
Release Date

Release Date

Type

Type

pom.sha512
Description

Description

Kamel
Kotlin Asynchronous Media Loading Library that supports Compose
Project URL

Project URL

https://github.com/alialbaali/Kamel
Source Code Management

Source Code Management

https://github.com/alialbaali/Kamel/tree/main

Download kamel-core-metadata

Dependencies

compile (6)

Group / Artifact Type Version
org.jetbrains.compose.ui : ui jar 0.3.2
org.jetbrains.compose.foundation : foundation jar 0.3.2
org.jetbrains.compose.runtime : runtime jar 0.3.2
io.ktor : ktor-client-core jar 1.5.1
io.ktor : ktor-client-logging jar 1.5.1
org.jetbrains.kotlin : kotlin-stdlib-jdk8 jar 1.4.31

Project Modules

There are no modules declared in this project.

Kamel

Version Snapshot License Kotlin Compose

Kamel is an asynchronous media loading library for Compose. It provides a simple, customizable and efficient way to load, cache, decode and display images in your application. By default, it uses Ktor client for loading resources.

Table of contents

Setup

Kamel is published on Maven Central:

repositories {
    mavenCentral()
    // ...
}

Multiplatform

Add the dependency to the common source-set:

kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("com.alialbaali.kamel:kamel-image:0.2.0")
                // ...
            }
        }
    }
}

Single-platform

Add the dependency to the dependencies block:

dependencies {
    implementation("com.alialbaali.kamel:kamel-image:0.2.0")
    // ...
}

Usage

Loading an image resource

To load an image, you can use lazyImageResource composable, it can load images from different data sources.

// String
lazyImageResource(data = "https://www.example.com/image.jpg")

// Ktor Url
lazyImageResource(data = Url("https://www.example.com/image.jpg"))

// URI
lazyImageResource(data = URI("https://www.example.com/image.png"))

// File
lazyImageResource(data = File("/path/to/image.png"))

// URL
lazyImageResource(data = URL("https://www.example.com/image.jpg"))

// and more...

Platform specific implementations

Since there isn't any shared resource system between Android and Desktop, some implementations (e.g. fetchers and mappers) are only available for a specific platform:

Desktop only implementations

To load an image file from desktop application resources, you have to add resourcesFetcher to the KamelConfig:

val desktopConfig = KamelConfig {
    takeFrom(KamelConfig.Default)
    resourcesFetcher() // Available only on Desktop.
}

Assuming there's an image.png file in the /resources directory in the project:

CompositionLocalProvider(LocalKamelConfig provides desktopConfig) {
    lazyImageResource("image.png")
}

Android only implementations

To load an image file from android application resources, you have to add resourcesFetcher and resourcesIdMapper to the KamelConfig:

val context : Context = LocalContext.current

val androidConfig = KamelConfig {
    takeFrom(KamelConfig.Default)
    resourcesFetcher(context) // Available only on Android.
    resourcesIdMapper(context) // Available only on Android. 
}

Assuming there's an image.png file in the /res/raw directory in the project:

CompositionLocalProvider(LocalKamelConfig provides androidConfig) {
    lazyImageResource(R.raw.image)
}

Configuring an image resource

lazyImageResource supports configuration using trailing lambda:

val imageResource: Resource<ImageBitmap> = lazyImageResource("https://www.example.com/image.jpg") {

    dispatcher = Dispatchers.IO // Coroutine Dispatcher to be used while loading.

    requestBuilder { // this: HttpRequestBuilder
        header("Key", "Value")
        parameter("Key", "Value")
        cacheControl(CacheControl.MAX_AGE)
    }

}

Displaying an image resource

KamelImage is a composable function that takes an ImageBitmap resource, display it and provide extra functionality:

KamelImage(
    resource = imageResource,
    contentDescription = "Profile"
)

KamelImage can display custom content in failure or loading states through onFailure and onLoading parameters:

KamelImage(
    resource = imageResource,
    contentDescription = "Profile",
    onLoading = {
        Box(modifier = Modifier.fillMaxSize()) {
            CircularProgressIndicator()
        }
    },
    onFailure = { exception ->
        Snackbar {
            Text(exception.message)
        }
    }
)

You can also provide your own custom implementation using a simple when expression:

when (val resource = lazyImageResource("https://www.example.com/image.jpg")) {
    is Resource.Loading -> {
        Text("Loading...")
    }
    is Resource.Success -> {
        val bitmap: ImageBitmap = resource.value
        Image(bitmap, null, modifier = Modifier.clip(CircleShape))
    }
    is Resource.Failure -> {
        log(resource.exception)
        val fallbackImage = imageResource("/path/to/fallbackImage.jpg")
        Image(fallbackImage, null)
    }
}

Crossfade animation

You can enable, disable or customize crossfade (fade-in) animation through the crossfade and animationSpec parameters:

KamelImage(
    resource = imageResource,
    contentDescription = "Profile",
    crossfade = true, // false by default
    animationSpec = tween(),
)

Configuring Kamel

The default implementation is KamelConfig.Default. If you wish to configure it, you can do it like so:

val myKamelConfig = KamelConfig {

    imageBitmapDecoder() // adds an ImageBitmapDecoder

    fileFetcher() // adds a FileFetcher

    httpFetcher { // Configuring Ktor HttpClient
        defaultRequest {
            url("https://www.example.com/")
            cacheControl(CacheControl.MaxAge(maxAgeSeconds = 10000))
        }
        Logging {
            level = LogLevel.INFO
            logger = Logger.SIMPLE
        }
    }

    // more functionality available.
}

Cache size (number of entries)

To Configure memory cache size, you can change the imageBitmapCacheSize property:

KamelConfig {
    imageBitmapCacheSize = 1000
}

Applying Kamel configuration

You can use LocalKamelConfig to apply your custom configuration:

CompositionLocalProvider(LocalKamelConfig provides myKamelConfig) {
    lazyImageResource("image.jpg")
}

Contributions

Contributions are always welcome!. If you'd like to contribute, please feel free to create a PR.

License

Copyright 2021 Ali Albaali

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Versions

Version
0.2.0
0.1.1
0.1.0
0.0.7
0.0.6