Rewrite FeedColors with some tests
This commit is contained in:
parent
d1e170a1b8
commit
d97da320b4
@ -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'
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
BIN
appcompose/src/androidTest/resources/favicon.ico
Normal file
BIN
appcompose/src/androidTest/resources/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
@ -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()
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user