All Projects → alialbaali → Kamel

alialbaali / Kamel

Licence: Apache-2.0 license
Kotlin asynchronous media loading and caching library for Compose.

Programming Languages

kotlin
9241 projects

Projects that are alternatives of or similar to Kamel

View-Load-ReTry
这个加载框架有点不一样,针对View进行加载,加载页面还保持了原View的属性,侧重点在灵活,哪里需要加载哪里,加载状态页面完全自定义,无任何限制,针对加载结果可以按需配置对应页面,LeakCanary检测无内存泄漏
Stars: ✭ 116 (-15.94%)
Mutual labels:  gif
gif-player
Control your animated GIFs
Stars: ✭ 120 (-13.04%)
Mutual labels:  gif
GiphyImageResultsPreview
Library for GIF results, preview, play, share everything at one place!
Stars: ✭ 28 (-79.71%)
Mutual labels:  gif
PCard
Demo project to showcase adding payment card details using JetPack Compose
Stars: ✭ 61 (-55.8%)
Mutual labels:  compose
gogif
The (no longer) missing GIF encoder for #golang
Stars: ✭ 21 (-84.78%)
Mutual labels:  gif
togglific
Do you find web animations distracting? Togglific provides a distraction-free web experience!
Stars: ✭ 17 (-87.68%)
Mutual labels:  gif
xvcode
web dynamic validation code generator 动态web校验码图片生成
Stars: ✭ 43 (-68.84%)
Mutual labels:  gif
SSSwiftUIGIFView
SSSwiftUIGIFView is a custom controller which helps to load GIF in SwiftUI.
Stars: ✭ 48 (-65.22%)
Mutual labels:  gif
StbSharp
C# port of the famous C framework
Stars: ✭ 62 (-55.07%)
Mutual labels:  gif
kev
Develop Kubernetes apps iteratively with Docker-Compose
Stars: ✭ 61 (-55.8%)
Mutual labels:  compose
ios-nd-gif-maker-swift
Resources for Udacity's Gif Maker app in Swift.
Stars: ✭ 13 (-90.58%)
Mutual labels:  gif
rocket-pipes
Powerful pipes for TypeScript, that chain Promise and ADT for you 🚌 -> ⛰️ -> 🚠 -> 🏂 -> 🚀
Stars: ✭ 18 (-86.96%)
Mutual labels:  compose
Root-Checker
Displays all root related info(Device Rooted, Root Available, Root Path, Root given, Busy Box installation) of an Android Device. Fully implemented in Jetpack compose using Material 3 dynamic theming and also has a separate implementation in xml with MDC 3.
Stars: ✭ 21 (-84.78%)
Mutual labels:  compose
AnyImageKit
A toolbox for pick/edit/capture photo or video. Written in Swift.
Stars: ✭ 580 (+320.29%)
Mutual labels:  gif
whatisnewdialog
An Android library for displaying a dialog where it presents new features in the app.
Stars: ✭ 22 (-84.06%)
Mutual labels:  gif
xaringanBuilder
An R package for building xaringan slides into multiple outputs, including html, pdf, png, gif, pptx, and mp4.
Stars: ✭ 157 (+13.77%)
Mutual labels:  gif
sail
The missing small and fast image decoding library for humans (not for machines) ⛵ https://sail.software
Stars: ✭ 206 (+49.28%)
Mutual labels:  gif
Among-Us-Dumpy-Gif-Maker
A tool to make dumpy among us GIFS
Stars: ✭ 537 (+289.13%)
Mutual labels:  gif
gifbar
🦄 Find Awesome Gif's right in your Menu Bar
Stars: ✭ 37 (-73.19%)
Mutual labels:  gif
GifReversingBot
A Reddit bot that reverses gifs
Stars: ✭ 38 (-72.46%)
Mutual labels:  gif

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()
    // ...
}

Multi-platform

Add the dependency to the common source-set:

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

Single-platform

Add the dependency to the dependencies block:

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

Ktor HttpClient Engine

Make sure to add a dependency for Ktor HttpClient engine for your platforms using this link.

Usage

Loading an image resource

To load an image asynchronously, you can use lazyPainterResource composable, it can load images from different data sources:

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

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

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

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

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

// and more...

lazyPainterResource can be used to load SVG, XML, JPEG, and PNG by default depending on the platform implementation.

lazyPainterResource returns a Resource<Painter> object which can be used to display the image using KamelImage composable.

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)
    // Available only on Desktop.
    resourcesFetcher()
}

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

CompositionLocalProvider(LocalKamelConfig provides desktopConfig) {
    lazyPainterResoursce("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)
    // Available only on Android.
    resourcesFetcher(context)
    // Available only on Android.
    resourcesIdMapper(context)
}

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

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

Configuring an image resource

lazyPainterResource supports configuration using a trailing lambda:

val painterResource: Resource<Painter> = lazyPainterResource("https://www.example.com/image.jpg") {

    // CoroutineContext to be used while loading the image.
    coroutineContext = Job() + Dispatcher.IO

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

}

Displaying an image resource

KamelImage is a composable function that takes a Resource<Painter> object, display it and provide extra functionality:

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

KamelImage can also be used to get the exception using onFailure, and progress using onLoading parameters, to display a snackbar or a progress indicator, depending on the case:

val coroutineScope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }
Box {
    KamelImage(
        resource = painterResource,
        contentDescription = "Profile",
        onLoading = { progress -> CircularProgressIndicator(progress) },
        onFailure = { exception ->
            coroutineScope.launch {
                snackbarHostState.showSnackbar(
                    message = exception.message.toString(),
                    actionLabel = "Hide",
                    duration = SnackbarDuration.Short
                )
            }
        }
    )
    SnackbarHost(hostState = snackbarHostState, modifier = Modifier.padding(16.dp))
}

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

when (val resource = lazyPainterResource("https://www.example.com/image.jpg")) {
    is Resource.Loading -> {
        Text("Loading...")
    }
    is Resource.Success -> {
        val painter: Painter = resource.value
        Image(painter, contentDescription = "Profile")
    }
    is Resource.Failure -> {
        log(resource.exception)
        val fallbackPainter = painterResource("/path/to/fallbackImage.jpg")
        Image(fallbackPainter, contentDescription = "Profile")
    }
}

Crossfade animation

You can enable, disable or customize crossfade (fade-in) animation through the animationSpec parameter. Setting animationSpec to null will disable the animation:

KamelImage(
    resource = imageResource,
    contentDescription = "Profile",
    // null by default
    animationSpec = tween(),
)

Configuring Kamel

The default implementation is KamelConfig.Default. If you wish to configure it, you can do it the following way:

val customKamelConfig = KamelConfig {
    // Copies the default implementation if needed
    takeFrom(KamelConfig.Default)

    // Sets the number of images to cache
    imageBitmapCacheSize = DefaultCacheSize

    // adds an ImageBitmapDecoder
    imageBitmapDecoder()

    // adds a FileFetcher
    fileFetcher()

    // Configures Ktor HttpClient
    httpFetcher {
        defaultRequest {
            url("https://www.example.com/")
            cacheControl(CacheControl.MaxAge(maxAgeSeconds = 10000))
        }

        install(HttpRequestRetry) {
            maxRetries = 3
            retryIf { httpRequest, httpResponse ->
                !httpResponse.status.isSuccess()
            }
        }
        
        // Requires adding "io.ktor:ktor-client-logging:$ktor_version"
        Logging {
            level = LogLevel.INFO
            logger = Logger.SIMPLE
        }
    }

    // more functionality available.
}

Cache size (number of entries to cache)

Kamel provides a generic Cache<K,V> interface, the default implementation uses LRU memory cache mechanism backed by LinkedHashMap. You can provide a number of entries to cache for each type like so:

KamelConfig {
    // 100 by default
    imageBitmapCacheSize = 500
    // 100 by default
    imageVectorCacheSize = 300
    // 100 by default
    svgCacheSize = 200
}

Applying Kamel configuration

You can use LocalKamelConfig to apply your custom configuration:

CompositionLocalProvider(LocalKamelConfig provides customKamelConfig) {
    lazyPainterResource("image.jpg")
}

Contributions

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

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.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].