Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# coil-imagegetter
Loads images for Html rendering in Android using [Coil](https://coil-kt.github.io/coil/)
Loads images for Html rendering in Android using [Coil3](https://coil-kt.github.io/coil/)

[![](https://jitpack.io/v/Commit451/coil-imagegetter.svg)](https://jitpack.io/#Commit451/coil-imagegetter)

Expand Down
47 changes: 0 additions & 47 deletions app/build.gradle

This file was deleted.

55 changes: 55 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}

android {
namespace = "com.commit451.coilimagegetter.sample"
compileSdk {
version = release(36)
}

defaultConfig {
applicationId = "com.commit451.coilimagegetter.sample"
minSdk = 21
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildFeatures {
viewBinding = true
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}

buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
}

dependencies {
implementation(libs.coil.network.okhttp)
implementation(libs.okhttp.coroutines)
implementation(libs.appcompat)
implementation(libs.core.ktx)
implementation(libs.commonmark)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.coroutines.android)
implementation(project(":coilimagegetter"))
}
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.commit451.coilimagegetter.sample">
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".App"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/com/commit451/coilimagegetter/sample/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.commit451.coilimagegetter.sample

import android.app.Application
import coil3.ImageLoader
import coil3.PlatformContext
import coil3.SingletonImageLoader
import coil3.request.crossfade

class App: Application(), SingletonImageLoader.Factory {
override fun newImageLoader(context: PlatformContext): ImageLoader {
return ImageLoader.Builder(context)
.crossfade(true)
.build()
}

}
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
package com.commit451.coilimagegetter.sample

import android.os.Build
import android.os.Bundle
import android.text.Html
import android.text.Spanned
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.parseAsHtml
import androidx.lifecycle.lifecycleScope
import com.commit451.coilimagegetter.CoilImageGetter
import com.commit451.coilimagegetter.sample.databinding.ActivityMainBinding
import kotlinx.coroutines.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.coroutines.executeAsync
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
import ru.gildor.coroutines.okhttp.await
import kotlin.coroutines.CoroutineContext

class MainActivity : AppCompatActivity(), CoroutineScope {
class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

private lateinit var job: Job

override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main

private val client = OkHttpClient.Builder()
.build()
private val renderer: HtmlRenderer = HtmlRenderer.builder()
Expand All @@ -35,27 +31,21 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
job = Job()

launch {
val deferred = async(Dispatchers.Default) {
lifecycleScope.launch {
val deferred = async(Dispatchers.IO) {
loadReadmeAsSpanned()
}
binding.textView.text = deferred.await()
}
}

override fun onDestroy() {
super.onDestroy()
job.cancel()
}

private suspend fun loadReadmeAsHtml(): String {
val request = Request.Builder()
.url("https://raw.githubusercontent.com/Jawnnypoo/open-meh/master/README.md")
.build()
val result = client.newCall(request).await()
val markdown = result.body?.string()
val result = client.newCall(request).executeAsync()
val markdown = result.body.string()

val document = parser.parse(markdown)
return renderer.render(document)
Expand All @@ -73,21 +63,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
}
)
return html.formatAsHtml(getter)
}

/**
* Assures HTML is formatted the same way pre and post Android N
*/
@Suppress("DEPRECATION")
fun String.formatAsHtml(
imageGetter: Html.ImageGetter? = null,
tagHandler: Html.TagHandler? = null
): Spanned {
return if (Build.VERSION.SDK_INT >= 24) {
Html.fromHtml(this, Html.FROM_HTML_MODE_LEGACY, imageGetter, tagHandler)
} else {
Html.fromHtml(this, imageGetter, tagHandler)
}
return html.parseAsHtml(imageGetter = getter, tagHandler = null)
}
}
22 changes: 0 additions & 22 deletions build.gradle

This file was deleted.

6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
}
35 changes: 0 additions & 35 deletions coilimagegetter/build.gradle

This file was deleted.

46 changes: 46 additions & 0 deletions coilimagegetter/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}

android {
namespace = "com.commit451.coilimagegetter"

compileSdk {
version = release(36)
}

defaultConfig {
minSdk = 21

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}

buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}

dependencies {
api(libs.coil)
}
2 changes: 1 addition & 1 deletion coilimagegetter/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<manifest package="com.commit451.coilimagegetter" />
<manifest/>
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.text.Html
import android.widget.TextView
import coil.Coil
import coil.ImageLoader
import coil.request.ImageRequest
import coil3.ImageLoader
import coil3.SingletonImageLoader
import coil3.asDrawable
import coil3.request.ImageRequest

/**
* An [Html.ImageGetter] implementation that uses Coil to load images.
Expand All @@ -19,21 +20,22 @@ import coil.request.ImageRequest
*/
open class CoilImageGetter(
private val textView: TextView,
private val imageLoader: ImageLoader = Coil.imageLoader(textView.context),
private val imageLoader: ImageLoader = SingletonImageLoader.get(textView.context),
private val sourceModifier: ((source: String) -> String)? = null
) : Html.ImageGetter {

override fun getDrawable(source: String): Drawable {
val finalSource = sourceModifier?.invoke(source) ?: source

val drawablePlaceholder = DrawablePlaceHolder()
imageLoader.enqueue(ImageRequest.Builder(textView.context).data(finalSource).apply {
target { drawable ->
drawablePlaceholder.updateDrawable(drawable)
val imageRequestBuilder = ImageRequest.Builder(textView.context)
.data(finalSource)
.target { drawable ->
drawablePlaceholder.updateDrawable(drawable.asDrawable(textView.resources))
// invalidating the drawable doesn't seem to be enough...
textView.text = textView.text
}
}.build())
imageLoader.enqueue(imageRequestBuilder.build())
// Since this loads async, we return a "blank" drawable, which we update
// later
return drawablePlaceholder
Expand Down
Loading