Rewrite FeedColors with some tests

This commit is contained in:
Shinokuni 2023-08-15 19:07:55 +02:00
parent d1e170a1b8
commit d97da320b4
5 changed files with 119 additions and 1 deletions

View File

@ -72,6 +72,7 @@ dependencies {
implementation composeBom
androidTestImplementation composeBom
implementation 'androidx.palette:palette-ktx:1.0.0'
implementation 'androidx.activity:activity-compose:1.7.2'
implementation 'androidx.compose.material3:material3'

View File

@ -0,0 +1,58 @@
package com.readrops.app.compose
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.readrops.api.apiModule
import com.readrops.api.utils.ApiUtils
import com.readrops.app.compose.utils.FeedColors
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import okio.Buffer
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.koin.dsl.module
import org.koin.test.KoinTestRule
import java.net.HttpURLConnection
import kotlin.test.assertTrue
class FeedColorsTest {
private val mockServer = MockWebServer()
@Before
fun before() {
val context = ApplicationProvider.getApplicationContext<Context>()
KoinTestRule.create {
modules(apiModule, module {
single { context }
})
}
mockServer.start()
}
@After
fun after() {
mockServer.shutdown()
}
@Test
fun getFeedColorTest() = runBlocking {
val stream = TestUtils.loadResource("favicon.ico")
mockServer.enqueue(
MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.addHeader(ApiUtils.CONTENT_TYPE_HEADER, "image/jpeg")
.setBody(Buffer().readFrom(stream))
)
val url = mockServer.url("/rss").toString()
val color = FeedColors.getFeedColor(url)
assertTrue { color != 0 }
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -1,14 +1,18 @@
package com.readrops.app.compose
import android.app.Application
import coil.ImageLoader
import coil.ImageLoaderFactory
import com.readrops.api.apiModule
import com.readrops.db.dbModule
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import org.koin.core.context.startKoin
import org.koin.core.logger.Level
open class ReadropsApp : Application() {
open class ReadropsApp : Application(), KoinComponent, ImageLoaderFactory {
override fun onCreate() {
super.onCreate()
@ -20,4 +24,11 @@ open class ReadropsApp : Application() {
modules(apiModule, dbModule, composeAppModule)
}
}
override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
.okHttpClient { get() }
.crossfade(true)
.build()
}
}

View File

@ -0,0 +1,48 @@
package com.readrops.app.compose.utils
import android.content.Context
import android.graphics.drawable.BitmapDrawable
import androidx.annotation.ColorInt
import androidx.palette.graphics.Palette
import coil.imageLoader
import coil.request.ImageRequest
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
object FeedColors : KoinComponent {
suspend fun getFeedColor(feedUrl: String): Int {
val context = get<Context>() // TODO maybe call imageLoader directly ? may require some DI changes
val result = context.imageLoader
.execute(
ImageRequest.Builder(context)
.data(feedUrl)
.allowHardware(false)
.build()
).drawable as BitmapDrawable
val palette = Palette.from(result.bitmap).generate()
val dominantSwatch = palette.dominantSwatch
return if (dominantSwatch != null && !isColorTooBright(dominantSwatch.rgb)
&& !isColorTooDark(dominantSwatch.rgb)) {
dominantSwatch.rgb
} else 0
}
private fun isColorTooBright(@ColorInt color: Int): Boolean {
return getColorLuma(color) > 210
}
private fun isColorTooDark(@ColorInt color: Int): Boolean {
return getColorLuma(color) < 40
}
private fun getColorLuma(@ColorInt color: Int): Double {
val r = color shr 16 and 0xff
val g = color shr 8 and 0xff
val b = color shr 0 and 0xff
return 0.2126 * r + 0.7152 * g + 0.0722 * b
}
}