Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updare README & docs #218

Merged
merged 8 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 104 additions & 97 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,78 @@ Compose Image library for Kotlin Multiplatform.

Add the dependency in your common module's commonMain sourceSet

```kotlin

```diff title="build.gradle.kts"
kotlin {
android()
ios()
// ...

sourceSets {
val commonMain by getting {
dependencies {
api("io.github.qdsfdhvh:image-loader:$last_version")
// api("io.github.qdsfdhvh:image-loader-extension-blur:$last_version")
+ api("io.github.qdsfdhvh:image-loader:1.6.0")
// optional - Moko Resources Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-moko-resources:1.6.0")
// optional - Blur Interceptor (only support bitmap)
+ api("io.github.qdsfdhvh:image-loader-extension-blur:1.6.0")
}
}
val jvmMain by getting {
dependencies {
// api("io.github.qdsfdhvh:image-loader-extension-imageio:$last_version")
// optional - ImageIO Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-imageio:1.6.0")
}
}
}
}

```

## How to Use

### 1.2.8 or Later (ing...)
### Display Image

```kotlin
val painter = rememberImagePainter("https://..")
Image(
painter = painter,
contentDescription = "image",
)
```

PS: default `Imageloader` will reload when it's displayed, is not friendly for `https` link, so it is recommended to custom `ImageLoader` and configure the cache.

#### ImageLoader
### Custom ImageLoader

I configure the `Imageloader {}` on each platform, you also can configure it in the `commonMain` like [Tachidesk-JUI](https://github.com/Suwayomi/Tachidesk-JUI/blob/master/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/image/ImageLoaderProvider.kt).

```kotlin
@Composable
fun Content() {
CompositionLocalProvider(
LocalImageLoader provides generateImageLoader(),
LocalImageLoader provides remember { generateImageLoader() },
) {
val url = "https://....."
val painter = rememberAsyncImagePainter(url)
Image(painter, null)
val painter = rememberImagePainter("https://..")
Image(
painter = painter,
contentDescription = "image",
)
}
}
```

// in android
#### in Android

```kotlin title="MainActivity.kt"
fun generateImageLoader(): ImageLoader {
return ImageLoader(/* requestCoroutineContext = Dispatchers.IO */) {
return ImageLoader {
options {
androidContext(applicationContext)
}
components {
setupDefaultComponents(
context,
httpClient = httpClient,
)
// or
// setupKtorComponents(httpClient)
// setupBase64Components()
// setupCommonComponents()
// setupJvmComponents()
// setupAndroidComponents(context, maxImageSize)
// or
// add(KtorUrlMapper())
// add(KtorUrlKeyer())
// add(KtorUrlFetcher.Factory(httpClient))
// ....
setupDefaultComponents()
}
interceptor {
addInterceptor(DoSomthingInterceptor())
memoryCacheConfig {
// Set the max size to 25% of the app's available memory.
maxSizePercent(context, 0.25)
Expand All @@ -75,110 +87,105 @@ fun generateImageLoader(): ImageLoader {
directory(context.cacheDir.resolve("image_cache").toOkioPath())
maxSizeBytes(512L * 1024 * 1024) // 512MB
}
// or
// useDefaultInterceptors = false
// addInterceptors(
// listOf(
// DoSomthingInterceptor(),
// MappedInterceptor(),
// MemoryCacheInterceptor(),
// DecodeInterceptor(),
// DiskCacheInterceptor(),
// FetchInterceptor(),
// )
// )
}
}
}
```

#### ImageRequest
#### in Jvm

```kotlin
val imageRequest = ImageRequest {
data(url)
components {
...
}
addInterceptor(DoSomthingInterceptor())
extra {
set("key_int", 11)
```kotlin title="Main.kt"
fun generateImageLoader(): ImageLoader {
return ImageLoader {
components {
setupDefaultComponents()
}
interceptor {
memoryCacheConfig {
maxSizeBytes(32 * 1024 * 1024) // 32MB
}
diskCacheConfig {
directory(getCacheDir().toOkioPath().resolve("image_cache"))
maxSizeBytes(512L * 1024 * 1024) // 512MB
}
}
}
}
val newImageRequest = newBuilder {
...

// about currentOperatingSystem, see app
private fun getCacheDir() = when (currentOperatingSystem) {
OperatingSystem.Windows -> File(System.getenv("AppData"), "$ApplicationName/cache")
OperatingSystem.Linux -> File(System.getProperty("user.home"), ".cache/$ApplicationName")
OperatingSystem.MacOS -> File(System.getProperty("user.home"), "Library/Caches/$ApplicationName")
else -> throw IllegalStateException("Unsupported operating system")
}
```

#### Memory/Disk cache support on all platforms
To enable caching on all platforms you have to setup custom ImageLoader
#### in iOS

```kotlin
internal expect fun ComponentRegistryBuilder.setupDefaultComponents()
internal expect fun getImageCacheDirectoryPath(): Path

private fun generateImageLoader(
memCacheSize: Int = 32 * 1024 * 1024, //32MB
diskCacheSize: Int = 512 * 1024 * 1024 //512MB
) = ImageLoader {
interceptor {
memoryCacheConfig {
maxSizeBytes(memCacheSize)
fun generateImageLoader(): ImageLoader {
return ImageLoader {
components {
setupDefaultComponents()
}
diskCacheConfig {
directory(getImageCacheDirectoryPath())
maxSizeBytes(diskCacheSize.toLong())
interceptor {
memoryCacheConfig {
maxSizeBytes(32 * 1024 * 1024) // 32MB
}
diskCacheConfig {
directory(getCacheDir().toPath().resolve("image_cache"))
maxSizeBytes(512L * 1024 * 1024) // 512MB
}
}
}
components {
setupDefaultComponents()
}
}

//actuals on the platforms:
//Android
actual fun ComponentRegistryBuilder.setupDefaultComponents() = this.setupDefaultComponents(App.context)
actual fun getImageCacheDirectoryPath(): Path = App.context.cacheDir.absolutePath.toPath()

//iOS
actual fun ComponentRegistryBuilder.setupDefaultComponents() = this.setupDefaultComponents()
actual fun getImageCacheDirectoryPath(): Path {
val cacheDir = NSSearchPathForDirectoriesInDomains(
private fun getCacheDir(): String {
return NSSearchPathForDirectoriesInDomains(
NSCachesDirectory,
NSUserDomainMask,
true
true,
).first() as String
return (cacheDir + "/media").toPath()
}

//Desktop
actual fun ComponentRegistryBuilder.setupDefaultComponents() = this.setupDefaultComponents()
actual fun getImageCacheDirectoryPath(): Path = "media/".toPath()
```
And provide it to composition

for more platform targets, see [app](app/).

#### ImageRequest

```kotlin
@Composable
fun App() {
CompositionLocalProvider(
LocalImageLoader provides generateImageLoader(),
) {
//your app here
val imageRequest = ImageRequest {
data(url)
addInterceptor(DoSomthingInterceptor())
components {
// ...
}
extra {
set("key_int", 11)
}
}
val newImageRequest = imageRequest.newBuilder {
// ...
}
```

### Before 1.2.8

`LocalImageLoader` has no default value, must be configured on each platform, and configuration is similar to `coil`.
`LocalImageLoader` has no default value, you must be configured on each platform, and configuration is similar to `coil`.

```kotlin
@Composable
fun Content() {
CompositionLocalProvider(
LocalImageLoader provides generateImageLoader(),
LocalImageLoader provides remember { generateImageLoader() },
) {
val url = "https://....."
val painter = rememberAsyncImagePainter(url)
Image(painter, null)
val painter = rememberAsyncImagePainter("https://.....")
Image(
painter = painter,
contentDescription = "image",
)
}
}

Expand Down
1 change: 0 additions & 1 deletion app/android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".DemoApp"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import com.seiko.imageloader.ImageLoader
import com.seiko.imageloader.LocalImageLoader
import com.seiko.imageloader.cache.memory.maxSizePercent
import com.seiko.imageloader.component.setupDefaultComponents
import com.seiko.imageloader.demo.util.commonConfig
import okio.Path.Companion.toOkioPath
Expand Down Expand Up @@ -38,8 +37,7 @@ private fun generateImageLoader(): ImageLoader {
}
interceptor {
memoryCacheConfig {
// Set the max size to 25% of the app's available memory.
maxSizePercent(0.25)
maxSizeBytes(32 * 1024 * 1024) // 32MB
}
diskCacheConfig {
directory(getCacheDir().toOkioPath().resolve("image_cache"))
Expand Down Expand Up @@ -76,4 +74,4 @@ private fun getCacheDir() = when (currentOperatingSystem) {
else -> throw IllegalStateException("Unsupported operating system")
}

private val ApplicationName = "Compose ImageLoader"
private const val ApplicationName = "Compose ImageLoader"
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.window.ComposeUIViewController
import com.seiko.imageloader.ImageLoader
import com.seiko.imageloader.LocalImageLoader
import com.seiko.imageloader.cache.memory.maxSizePercent
import com.seiko.imageloader.component.setupDefaultComponents
import com.seiko.imageloader.demo.util.commonConfig
import okio.Path.Companion.toPath
import platform.Foundation.NSCachesDirectory
import platform.Foundation.NSFileManager
import platform.Foundation.NSSearchPathForDirectoriesInDomains
import platform.Foundation.NSUserDomainMask
import platform.UIKit.UIViewController

Expand All @@ -31,8 +30,7 @@ private fun generateImageLoader(): ImageLoader {
}
interceptor {
memoryCacheConfig {
// Set the max size to 25% of the app's available memory.
maxSizePercent(0.25)
maxSizeBytes(32 * 1024 * 1024) // 32MB
}
diskCacheConfig {
directory(getCacheDir().toPath().resolve("image_cache"))
Expand All @@ -43,11 +41,9 @@ private fun generateImageLoader(): ImageLoader {
}

private fun getCacheDir(): String {
return NSFileManager.defaultManager.URLForDirectory(
return NSSearchPathForDirectoriesInDomains(
NSCachesDirectory,
NSUserDomainMask,
null,
true,
null,
)!!.path.orEmpty()
).first() as String
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.window.Window
import com.seiko.imageloader.ImageLoader
import com.seiko.imageloader.LocalImageLoader
import com.seiko.imageloader.cache.memory.maxSizePercent
import com.seiko.imageloader.component.setupDefaultComponents
import com.seiko.imageloader.demo.util.commonConfig
import okio.Path.Companion.toPath
import platform.AppKit.NSApp
import platform.AppKit.NSApplication
import platform.Foundation.NSCachesDirectory
import platform.Foundation.NSFileManager
import platform.Foundation.NSSearchPathForDirectoriesInDomains
import platform.Foundation.NSUserDomainMask

fun main() {
Expand All @@ -35,8 +34,7 @@ private fun generateImageLoader(): ImageLoader {
}
interceptor {
memoryCacheConfig {
// Set the max size to 25% of the app's available memory.
maxSizePercent(0.25)
maxSizeBytes(32 * 1024 * 1024) // 32MB
}
diskCacheConfig {
directory(getCacheDir().toPath().resolve("image_cache"))
Expand All @@ -47,11 +45,9 @@ private fun generateImageLoader(): ImageLoader {
}

private fun getCacheDir(): String {
return NSFileManager.defaultManager.URLForDirectory(
return NSSearchPathForDirectoriesInDomains(
NSCachesDirectory,
NSUserDomainMask,
null,
true,
null,
)!!.path.orEmpty()
).first() as String
}
Loading