Skip to content

Commit

Permalink
[1.52.*] Pre-release merge (#270)
Browse files Browse the repository at this point in the history
  • Loading branch information
tramline-github[bot] authored Feb 1, 2024
2 parents 3a634b0 + dd2a89b commit befb84c
Show file tree
Hide file tree
Showing 18 changed files with 232 additions and 395 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
import io.ktor.http.HttpStatusCode
import io.sentry.kotlin.multiplatform.Sentry
import kotlinx.coroutines.withContext
import me.tatarka.inject.annotations.Inject

Expand All @@ -38,14 +37,13 @@ class PostSourceFetcher(
val response = httpClient.get(link)
if (response.status == HttpStatusCode.OK) {
try {
response.bodyAsText()
return@withContext response.bodyAsText()
} catch (e: Exception) {
Sentry.captureException(e)
null
// no-op
}
} else {
null
}

return@withContext null
}
}
}
6 changes: 4 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ androidx_work = "2.9.0"
androidx_datastore = "1.1.0-beta01"
androidx_browser = "1.7.0"
androidx_annotation = "1.7.1"
coil = "2.5.0"
coil = "3.0.0-alpha03"
spotless = "6.25.0"
ktfmt = "0.44"
kotlininject = "0.6.3"
Expand Down Expand Up @@ -89,7 +89,9 @@ androidx_datastore_okio = { module = "androidx.datastore:datastore-core-okio", v
androidx_datastore_preferences = { module = "androidx.datastore:datastore-preferences-core", version.ref = "androidx_datastore" }
androidx_browser = { module = "androidx.browser:browser", version.ref = "androidx_browser" }
androidx_annotation= { module = "androidx.annotation:annotation", version.ref = "androidx_annotation" }
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
coil_compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" }
coil_network = { module = "io.coil-kt.coil3:coil-network-ktor", version.ref = "coil" }
coil_svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" }
kotlininject-compiler = { module = 'me.tatarka.inject:kotlin-inject-compiler-ksp', version.ref = 'kotlininject' }
kotlininject-runtime = { module = 'me.tatarka.inject:kotlin-inject-runtime', version.ref = 'kotlininject' }
material_color_utilities = { module = "dev.sasikanth:material-color-utilities", version.ref = "material_color_utilities" }
Expand Down
4 changes: 3 additions & 1 deletion shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ kotlin {
implementation(libs.bundles.xmlutil)
api(libs.webview)
implementation(libs.uuid)
api(libs.coil.compose)
api(libs.coil.network)
api(libs.coil.svg)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
Expand All @@ -134,7 +137,6 @@ kotlin {
api(libs.androidx.browser)
implementation(libs.ktor.client.okhttp)
implementation(libs.sqldelight.driver.android)
implementation(libs.coil.compose)
api(libs.sqliteAndroid)
}
val androidInstrumentedTest by getting {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Sasikanth Miriyampalli
* Copyright 2024 Sasikanth Miriyampalli
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dev.sasikanth.rss.reader.di

import dev.sasikanth.rss.reader.components.AndroidImageLoader
import dev.sasikanth.rss.reader.components.image.ImageLoader
import android.content.Context
import coil3.PlatformContext
import me.tatarka.inject.annotations.Provides
import okio.Path
import okio.Path.Companion.toPath

actual interface ImageLoaderPlatformComponent {

internal actual interface ImageLoaderComponent {
@Provides fun providePlatformContext(context: Context): PlatformContext = context

@Provides fun AndroidImageLoader.bind(): ImageLoader = this
@Provides
fun diskCache(application: Context): Path =
application.cacheDir.absolutePath.toPath().resolve("dev_sasikanth_rss_reader_images_cache")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2024 Sasikanth Miriyampalli
*
* 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
*
* http://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.
*/

package dev.sasikanth.rss.reader.utils

import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.core.graphics.drawable.toBitmap
import coil3.Image
import coil3.PlatformContext
import coil3.annotation.ExperimentalCoilApi

@OptIn(ExperimentalCoilApi::class)
actual fun Image.toComposeImageBitmap(context: PlatformContext): ImageBitmap {
return asDrawable(context.resources).toBitmap().asImageBitmap()
}
13 changes: 7 additions & 6 deletions shared/src/commonMain/kotlin/dev/sasikanth/rss/reader/app/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSiz
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import coil3.ImageLoader
import coil3.annotation.ExperimentalCoilApi
import coil3.compose.setSingletonImageLoaderFactory
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.StackAnimation
import com.arkivanov.essenty.backhandler.BackHandler
import dev.sasikanth.rss.reader.about.ui.AboutScreen
import dev.sasikanth.rss.reader.bookmarks.ui.BookmarksScreen
import dev.sasikanth.rss.reader.components.DynamicContentTheme
import dev.sasikanth.rss.reader.components.LocalDynamicColorState
import dev.sasikanth.rss.reader.components.image.ImageLoader
import dev.sasikanth.rss.reader.components.image.LocalImageLoader
import dev.sasikanth.rss.reader.components.rememberDynamicColorState
import dev.sasikanth.rss.reader.home.ui.HomeScreen
import dev.sasikanth.rss.reader.platform.LinkHandler
Expand All @@ -48,17 +48,18 @@ typealias App = @Composable () -> Unit

@Inject
@Composable
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class, ExperimentalCoilApi::class)
fun App(
appPresenter: AppPresenter,
imageLoader: ImageLoader,
shareHandler: ShareHandler,
linkHandler: LinkHandler,
imageLoader: ImageLoader,
) {
setSingletonImageLoaderFactory { imageLoader }

val dynamicColorState = rememberDynamicColorState(imageLoader = imageLoader)

CompositionLocalProvider(
LocalImageLoader provides imageLoader,
LocalWindowSizeClass provides calculateWindowSizeClass(),
LocalDynamicColorState provides dynamicColorState,
LocalShareHandler provides shareHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.unit.IntSize
import coil3.ImageLoader
import coil3.PlatformContext
import coil3.annotation.ExperimentalCoilApi
import coil3.compose.LocalPlatformContext
import coil3.request.ImageRequest
import coil3.size.Scale
import dev.sasikanth.material.color.utilities.dynamiccolor.DynamicColor
import dev.sasikanth.material.color.utilities.dynamiccolor.MaterialDynamicColors
import dev.sasikanth.material.color.utilities.dynamiccolor.ToneDeltaConstraint
Expand All @@ -39,12 +44,13 @@ import dev.sasikanth.material.color.utilities.quantize.QuantizerCelebi
import dev.sasikanth.material.color.utilities.scheme.DynamicScheme
import dev.sasikanth.material.color.utilities.scheme.SchemeContent
import dev.sasikanth.material.color.utilities.score.Score
import dev.sasikanth.rss.reader.components.image.ImageLoader
import dev.sasikanth.rss.reader.ui.AppTheme
import dev.sasikanth.rss.reader.utils.Constants.EPSILON
import dev.sasikanth.rss.reader.utils.inverse
import dev.sasikanth.rss.reader.utils.toComposeImageBitmap
import kotlin.math.absoluteValue
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.withContext

private const val TINTED_BACKGROUND = "tinted_background"
Expand All @@ -64,7 +70,7 @@ private const val SURFACE_CONTAINER_HIGHEST = "surface_container_highest"

@Composable
internal fun DynamicContentTheme(
dynamicColorState: DynamicColorState = rememberDynamicColorState(),
dynamicColorState: DynamicColorState,
content: @Composable () -> Unit
) {
val colorScheme =
Expand Down Expand Up @@ -104,8 +110,9 @@ internal fun rememberDynamicColorState(
defaultSurfaceContainerLowest: Color = AppTheme.colorScheme.surfaceContainerLowest,
defaultSurfaceContainerHigh: Color = AppTheme.colorScheme.surfaceContainerHigh,
defaultSurfaceContainerHighest: Color = AppTheme.colorScheme.surfaceContainerHighest,
imageLoader: ImageLoader? = null
imageLoader: ImageLoader,
): DynamicColorState {
val platformContext = LocalPlatformContext.current
return rememberSaveable(saver = DynamicColorState.Saver) {
DynamicColorState(
defaultTintedBackground,
Expand All @@ -124,7 +131,7 @@ internal fun rememberDynamicColorState(
defaultSurfaceContainerHighest,
)
}
.also { it.setImageLoader(imageLoader) }
.apply { setImageLoader(imageLoader, platformContext) }
}

/**
Expand Down Expand Up @@ -199,7 +206,9 @@ internal class DynamicColorState(
else -> null
}
private var images = emptyList<String>()
private var imageLoader: ImageLoader? = null

private lateinit var imageLoader: ImageLoader
private lateinit var platformContext: PlatformContext

companion object {
val Saver: Saver<DynamicColorState, *> =
Expand Down Expand Up @@ -245,15 +254,16 @@ internal class DynamicColorState(
)
}

fun setImageLoader(imageLoader: ImageLoader?) {
fun setImageLoader(imageLoader: ImageLoader, platformContext: PlatformContext) {
this.imageLoader = imageLoader
this.platformContext = platformContext
}

suspend fun onContentChange(images: List<String>) {
if (!this.images.containsAll(images)) {
this.images = images
this.images.forEach { imageUrl -> fetchDynamicColors(imageUrl) }
suspend fun onContentChange(newImages: List<String>) {
if (images.isEmpty()) {
images = newImages
}
images.forEach { imageUrl -> fetchDynamicColors(imageUrl) }
}

fun updateOffset(
Expand All @@ -262,6 +272,7 @@ internal class DynamicColorState(
nextImageUrl: String?,
offset: Float
) {

val previousDynamicColors = previousImageUrl?.let { cache?.get(it) }
val currentDynamicColors = cache?.get(currentImageUrl)
val nextDynamicColors = nextImageUrl?.let { cache?.get(it) }
Expand Down Expand Up @@ -397,14 +408,27 @@ internal class DynamicColorState(
surfaceContainerHighest = defaultSurfaceContainerHighest
}

@OptIn(ExperimentalCoilApi::class)
private suspend fun fetchDynamicColors(url: String): DynamicColors? {
val cached = cache?.get(url)
if (cached != null) {
// If we already have the result cached, return early now...
return cached
}

val image = imageLoader?.getImage(url, size = IntSize(64, 64))
val imageRequest =
ImageRequest.Builder(platformContext)
.data(url)
.scale(Scale.FILL)
.size(64)
.memoryCacheKey("$url.dynamic_colors")
.build()

val image =
withContext(Dispatchers.IO) {
imageLoader.execute(imageRequest).image?.toComposeImageBitmap(platformContext)
}

return if (image != null) {
extractColorsFromImage(image)
.let { colorsMap ->
Expand Down
Loading

0 comments on commit befb84c

Please sign in to comment.