From a7e22d9addb39a890b21a6f4153a70ef0471ad44 Mon Sep 17 00:00:00 2001 From: T8RIN Date: Fri, 15 Nov 2024 01:13:31 +0300 Subject: [PATCH] kotlin 2.0.21, coil3 --- app/build.gradle.kts | 17 +- benchmark/build.gradle.kts | 9 +- build-logic/convention/build.gradle.kts | 6 +- .../ImageToolboxLibraryComposePlugin.kt | 26 +-- .../t8rin/imagetoolbox/ConfigureCompose.kt | 28 ++- .../imagetoolbox/ConfigureKotlinAndroid.kt | 58 +++--- build.gradle.kts | 1 + core/data/build.gradle.kts | 5 +- .../core/data/coil/AnimatedJxlDecoderCoil2.kt | 177 ------------------ .../core/data/coil/HeifDecoderCoil2.kt | 128 ------------- .../core/data/coil/TimeMeasureInterceptor.kt | 7 +- .../core/data/di/ImageLoaderModule.kt | 40 ++-- .../core/data/image/AndroidImageGetter.kt | 19 +- .../core/data/image/AndroidImageScaler.kt | 7 +- .../data/image/AndroidImageTransformer.kt | 15 +- .../core/data/image/utils/BlendingModeExt.kt | 3 +- .../core/data/utils/BitmapUtils.kt | 8 - .../core/data/utils/CoilUtils.kt | 8 +- .../presentation/widget/AddFiltersSheet.kt | 2 +- .../widget/FilterSelectionItem.kt | 12 +- .../widget/FilterTemplateInfoSheet.kt | 8 +- .../widget/TemplateFilterSelectionItem.kt | 12 +- core/ui/build.gradle.kts | 4 +- .../transformation/ImageInfoTransformation.kt | 8 +- .../core/ui/utils/helper/CoilUtils.kt | 8 +- .../ui/utils/provider/LocalImageLoader.kt | 2 +- .../core/ui/widget/image/Picture.kt | 19 +- .../core/ui/widget/image/UrisCarousel.kt | 6 +- .../core/ui/widget/other/EmojiItem.kt | 5 +- .../widget/sheets/PickImageFromUrisSheet.kt | 2 +- .../core/ui/widget/sheets/ZoomModalSheet.kt | 7 +- .../components/utils/DrawUtils.kt | 6 +- .../data/model/GPUFilterTransformation.kt | 8 +- .../screenLogic/GradientMakerComponent.kt | 2 +- .../components/ImagePreviewGrid.kt | 6 +- .../presentation/ImageSplitterContent.kt | 3 +- .../presentation/LoadNetImageContent.kt | 6 +- .../screenLogic/MediaPickerComponent.kt | 2 +- .../pdf_tools/data/AndroidPdfManager.kt | 14 +- .../presentation/components/PdfViewer.kt | 24 ++- .../recognize/text/domain/TessParams.kt | 2 +- .../text/presentation/RecognizeTextContent.kt | 6 +- .../screenLogic/RecognizeTextComponent.kt | 2 +- .../presentation/screenLogic/RootComponent.kt | 2 +- .../components/FilterEditOption.kt | 4 +- .../presentation/WatermarkingContent.kt | 6 +- .../screenLogic/WatermarkingComponent.kt | 2 +- gradle/libs.versions.toml | 32 ++-- 48 files changed, 257 insertions(+), 527 deletions(-) delete mode 100644 core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/AnimatedJxlDecoderCoil2.kt delete mode 100644 core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/HeifDecoderCoil2.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3aff28b94..0bf515d5b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,7 +17,7 @@ @file:Suppress("UnstableApiUsage") -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") @@ -28,6 +28,7 @@ plugins { id("com.google.gms.google-services") id("com.google.firebase.crashlytics") id("com.mikepenz.aboutlibraries.plugin") + id("org.jetbrains.kotlin.plugin.compose") } android { @@ -38,14 +39,14 @@ android { defaultConfig { vectorDrawables.useSupportLibrary = true - + applicationId = "ru.tech.imageresizershrinker" minSdk = libs.versions.androidMinSdk.get().toIntOrNull() targetSdk = libs.versions.androidTargetSdk.get().toIntOrNull() versionCode = libs.versions.versionCode.get().toIntOrNull() versionName = System.getenv("VERSION_NAME") ?: libs.versions.versionName.get() - archivesName.set("image-toolbox-$versionName${if (isFoss) "-foss" else ""}") + setProperty("archivesBaseName", "image-toolbox-$versionName${if (isFoss) "-foss" else ""}") } androidResources { @@ -92,12 +93,10 @@ android { isCoreLibraryDesugaringEnabled = true } - kotlinOptions { - jvmTarget = javaVersion.toString() - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmTarget.get())) + } } buildFeatures { diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index fe049cdd1..b376284ef 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -17,6 +17,9 @@ @file:Suppress("UnstableApiUsage") +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + + plugins { id("com.android.test") id("org.jetbrains.kotlin.android") @@ -39,8 +42,10 @@ android { targetCompatibility = JavaVersion.toVersion(libs.versions.jvmTarget.get()) } - kotlinOptions { - jvmTarget = libs.versions.jvmTarget.get() + kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.fromTarget(libs.versions.jvmTarget.get())) + } } buildTypes { diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts index 9e2d36bfe..71fe9e48d 100644 --- a/build-logic/convention/build.gradle.kts +++ b/build-logic/convention/build.gradle.kts @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -30,8 +31,8 @@ java { targetCompatibility = JavaVersion.VERSION_17 } tasks.withType().configureEach { - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) } } @@ -39,6 +40,7 @@ dependencies { compileOnly(libs.agp.gradle) compileOnly(libs.kotlin.gradle) compileOnly(libs.detekt.gradle) + compileOnly(libs.compose.compiler.gradle) } gradlePlugin { diff --git a/build-logic/convention/src/main/kotlin/ImageToolboxLibraryComposePlugin.kt b/build-logic/convention/src/main/kotlin/ImageToolboxLibraryComposePlugin.kt index 0c75c53d4..b3059922f 100644 --- a/build-logic/convention/src/main/kotlin/ImageToolboxLibraryComposePlugin.kt +++ b/build-logic/convention/src/main/kotlin/ImageToolboxLibraryComposePlugin.kt @@ -17,35 +17,19 @@ import com.android.build.api.dsl.LibraryExtension import com.t8rin.imagetoolbox.configureCompose -import com.t8rin.imagetoolbox.libs import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.withType -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.getByType @Suppress("UNUSED") class ImageToolboxLibraryComposePlugin : Plugin { override fun apply(target: Project) { with(target) { - dependencies { - "implementation"(libs.findLibrary("androidx.material3").get()) - "implementation"(libs.findLibrary("androidx.material3.window.sizeclass").get()) - "implementation"(libs.findLibrary("androidx.material").get()) - "implementation"(libs.findLibrary("androidx.material.icons.extended").get()) - } + apply(plugin = "com.android.library") + apply(plugin = "org.jetbrains.kotlin.plugin.compose") - extensions.configure { - configureCompose(this) - } - - tasks.withType { - compilerOptions.freeCompilerArgs.addAll( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:strongSkipping=true", - ) - } + configureCompose(extensions.getByType()) } } } diff --git a/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureCompose.kt b/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureCompose.kt index 7afd3e6a4..a6cb2cd93 100644 --- a/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureCompose.kt +++ b/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureCompose.kt @@ -19,6 +19,11 @@ package com.t8rin.imagetoolbox import com.android.build.api.dsl.CommonExtension import org.gradle.api.Project +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginExtension +import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag internal fun Project.configureCompose( commonExtension: CommonExtension<*, *, *, *, *, *>, @@ -28,15 +33,20 @@ internal fun Project.configureCompose( compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("compose.compiler").get().toString() - } - kotlinOptions { - freeCompilerArgs += listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:stabilityConfigurationPath=" + - "${project.rootProject.projectDir.absolutePath}/compose_compiler_config.conf" - ) + dependencies { + "implementation"(libs.findLibrary("androidx.material3").get()) + "implementation"(libs.findLibrary("androidx.material3.window.sizeclass").get()) + "implementation"(libs.findLibrary("androidx.material").get()) + "implementation"(libs.findLibrary("androidx.material.icons.extended").get()) } } + + extensions.configure { + featureFlags = setOf( + ComposeFeatureFlag.OptimizeNonSkippingGroups + ) + + stabilityConfigurationFile = + rootProject.layout.projectDirectory.file("compose_compiler_config.conf") + } } diff --git a/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureKotlinAndroid.kt b/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureKotlinAndroid.kt index 843b49a86..7e3f45cac 100644 --- a/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureKotlinAndroid.kt +++ b/build-logic/convention/src/main/kotlin/com/t8rin/imagetoolbox/ConfigureKotlinAndroid.kt @@ -20,11 +20,14 @@ package com.t8rin.imagetoolbox import com.android.build.api.dsl.CommonExtension import org.gradle.api.JavaVersion import org.gradle.api.Project -import org.gradle.api.plugins.ExtensionAware +import org.gradle.kotlin.dsl.assign +import org.gradle.kotlin.dsl.configure import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.withType -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.gradle.kotlin.dsl.provideDelegate +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension internal fun Project.configureKotlinAndroid( commonExtension: CommonExtension<*, *, *, *, *, *>, @@ -72,26 +75,9 @@ internal fun Project.configureKotlinAndroid( disable += "UsingMaterialAndMaterial3Libraries" disable += "ModifierParameter" } - - kotlinOptions { - freeCompilerArgs += listOf( - "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", - "-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi", - "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", - "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", - "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", - "-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi", - "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", - ) - jvmTarget = javaVersion.toString() - } } - tasks.withType().configureEach { - kotlinOptions { - jvmTarget = javaVersion.toString() - } - } + configureKotlin() dependencies { add("coreLibraryDesugaring", libs.findLibrary("desugaring").get()) @@ -103,6 +89,28 @@ val Project.javaVersion: JavaVersion libs.findVersion("jvmTarget").get().toString() ) -fun CommonExtension<*, *, *, *, *, *>.kotlinOptions(block: KotlinJvmOptions.() -> Unit) { - (this as ExtensionAware).extensions.configure("kotlinOptions", block) -} +/** + * Configure base Kotlin options + */ +private inline fun Project.configureKotlin() = configure { + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + val warningsAsErrors: String? by project + when (this) { + is KotlinAndroidProjectExtension -> compilerOptions + is KotlinJvmProjectExtension -> compilerOptions + else -> TODO("Unsupported project extension $this ${T::class}") + }.apply { + jvmTarget = JvmTarget.fromTarget(libs.findVersion("jvmTarget").get().toString()) + allWarningsAsErrors = warningsAsErrors.toBoolean() + freeCompilerArgs.addAll( + "-opt-in=androidx.compose.material3.ExperimentalMaterial3Api", + "-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi", + "-opt-in=androidx.compose.animation.ExperimentalAnimationApi", + "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi", + "-opt-in=androidx.compose.foundation.layout.ExperimentalLayoutApi", + "-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi", + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + ) + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index fec843dad..d055fe28f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,7 @@ buildscript { classpath(libs.baselineprofile.gradle) classpath(libs.detekt.gradle) classpath(libs.aboutlibraries.gradle) + classpath(libs.compose.compiler.gradle) } } diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index f46cbca8e..525b58ebc 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -24,10 +24,13 @@ android.namespace = "ru.tech.imageresizershrinker.core.data" dependencies { api(libs.coil) - api(libs.coilCompose) + api(libs.coilNetwork) + api(libs.ktor) implementation(libs.coilGif) implementation(libs.coilSvg) + implementation(libs.androidx.compose.ui.graphics) + api(libs.datastore.preferences.android) implementation(libs.avif.coder.coil) { diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/AnimatedJxlDecoderCoil2.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/AnimatedJxlDecoderCoil2.kt deleted file mode 100644 index d9a62a18f..000000000 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/AnimatedJxlDecoderCoil2.kt +++ /dev/null @@ -1,177 +0,0 @@ -/* - * ImageToolbox is an image editor for android - * Copyright (c) 2024 T8RIN (Malik Mukhametzyanov) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * 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. - * - * You should have received a copy of the Apache License - * along with this program. If not, see . - */ - -package ru.tech.imageresizershrinker.core.data.coil - -import android.content.Context -import android.graphics.Bitmap -import android.graphics.drawable.BitmapDrawable -import android.graphics.drawable.Drawable -import android.os.Build -import coil.ImageLoader -import coil.decode.DecodeResult -import coil.decode.Decoder -import coil.fetch.SourceResult -import coil.request.Options -import coil.size.Scale -import coil.size.Size -import coil.size.pxOrElse -import com.awxkee.jxlcoder.JxlAnimatedImage -import com.awxkee.jxlcoder.JxlResizeFilter -import com.awxkee.jxlcoder.PreferredColorConfig -import com.awxkee.jxlcoder.ScaleMode -import com.awxkee.jxlcoder.animation.AnimatedDrawable -import com.awxkee.jxlcoder.animation.JxlAnimatedStore -import kotlinx.coroutines.runInterruptible -import okio.BufferedSource -import okio.ByteString.Companion.toByteString - -internal class AnimatedJxlDecoderCoil2( - private val source: SourceResult, - private val options: Options, - private val context: Context, - private val preheatFrames: Int, - private val exceptionLogger: ((Exception) -> Unit)? = null, -) : Decoder { - - override suspend fun decode(): DecodeResult? = runInterruptible { - try { - // ColorSpace is preferred to be ignored due to lib is trying to handle all color profile by itself - val sourceData = source.source.source().readByteArray() - - var mPreferredColorConfig: PreferredColorConfig = when (options.config) { - Bitmap.Config.ALPHA_8 -> PreferredColorConfig.RGBA_8888 - Bitmap.Config.RGB_565 -> if (options.allowRgb565) PreferredColorConfig.RGB_565 else PreferredColorConfig.DEFAULT - Bitmap.Config.ARGB_8888 -> PreferredColorConfig.RGBA_8888 - else -> PreferredColorConfig.DEFAULT - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && options.config == Bitmap.Config.RGBA_F16) { - mPreferredColorConfig = PreferredColorConfig.RGBA_F16 - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.config == Bitmap.Config.HARDWARE) { - mPreferredColorConfig = PreferredColorConfig.HARDWARE - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && options.config == Bitmap.Config.RGBA_1010102) { - mPreferredColorConfig = PreferredColorConfig.RGBA_1010102 - } - - if (options.size == Size.ORIGINAL) { - val originalImage = JxlAnimatedImage( - byteArray = sourceData, - preferredColorConfig = mPreferredColorConfig - ) - return@runInterruptible DecodeResult( - drawable = originalImage.drawable(), - isSampled = false - ) - } - - val dstWidth = options.size.width.pxOrElse { 0 } - val dstHeight = options.size.height.pxOrElse { 0 } - val scaleMode = when (options.scale) { - Scale.FILL -> ScaleMode.FILL - Scale.FIT -> ScaleMode.FIT - } - - val originalImage = JxlAnimatedImage( - byteArray = sourceData, - preferredColorConfig = mPreferredColorConfig, - scaleMode = scaleMode, - jxlResizeFilter = JxlResizeFilter.BILINEAR - ) - - DecodeResult( - drawable = originalImage.drawable( - dstWidth = dstWidth, - dstHeight = dstHeight - ), - isSampled = true - ) - } catch (e: Exception) { - exceptionLogger?.invoke(e) - return@runInterruptible null - } - } - - private fun JxlAnimatedImage.drawable( - dstWidth: Int = 0, - dstHeight: Int = 0 - ): Drawable = if (numberOfFrames > 1) { - AnimatedDrawable( - frameStore = JxlAnimatedStore( - jxlAnimatedImage = this, - targetWidth = dstWidth, - targetHeight = dstHeight - ), - preheatFrames = preheatFrames, - firstFrameAsPlaceholder = true - ) - } else { - BitmapDrawable( - context.resources, - getFrame( - frame = 0, - scaleWidth = dstWidth, - scaleHeight = dstHeight - ) - ) - } - - class Factory( - private val context: Context, - private val preheatFrames: Int = 6, - private val exceptionLogger: ((Exception) -> Unit)? = null, - ) : Decoder.Factory { - override fun create( - result: SourceResult, - options: Options, - imageLoader: ImageLoader, - ) = if (isJXL(result.source.source())) { - AnimatedJxlDecoderCoil2( - source = result, - options = options, - context = context, - preheatFrames = preheatFrames, - exceptionLogger = exceptionLogger, - ) - } else null - - companion object { - private val MAGIC_1 = byteArrayOf(0xFF.toByte(), 0x0A).toByteString() - private val MAGIC_2 = byteArrayOf( - 0x0.toByte(), - 0x0.toByte(), - 0x0.toByte(), - 0x0C.toByte(), - 0x4A, - 0x58, - 0x4C, - 0x20, - 0x0D, - 0x0A, - 0x87.toByte(), - 0x0A - ).toByteString() - - private fun isJXL(source: BufferedSource): Boolean { - return source.rangeEquals(0, MAGIC_1) || source.rangeEquals( - 0, - MAGIC_2 - ) - } - } - } - -} \ No newline at end of file diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/HeifDecoderCoil2.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/HeifDecoderCoil2.kt deleted file mode 100644 index 415c40e11..000000000 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/HeifDecoderCoil2.kt +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ImageToolbox is an image editor for android - * Copyright (c) 2024 T8RIN (Malik Mukhametzyanov) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * 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. - * - * You should have received a copy of the Apache License - * along with this program. If not, see . - */ - -package ru.tech.imageresizershrinker.core.data.coil - -import android.graphics.Bitmap -import android.graphics.drawable.BitmapDrawable -import android.os.Build -import coil.ImageLoader -import coil.decode.DecodeResult -import coil.decode.Decoder -import coil.fetch.SourceResult -import coil.request.Options -import coil.size.Scale -import coil.size.pxOrElse -import com.radzivon.bartoshyk.avif.coder.HeifCoder -import com.radzivon.bartoshyk.avif.coder.PreferredColorConfig -import com.radzivon.bartoshyk.avif.coder.ScaleMode -import kotlinx.coroutines.runInterruptible -import okio.ByteString.Companion.encodeUtf8 - -internal class HeifDecoderCoil2( - private val source: SourceResult, - private val options: Options, - private val exceptionLogger: ((Exception) -> Unit)? = null, -) : Decoder { - - private val coder = HeifCoder() - - override suspend fun decode(): DecodeResult? = runInterruptible { - try { - // ColorSpace is preferred to be ignored due to lib is trying to handle all color profile by itself - val sourceData = source.source.source().readByteArray() - - var mPreferredColorConfig: PreferredColorConfig = when (options.config) { - Bitmap.Config.ALPHA_8 -> PreferredColorConfig.RGBA_8888 - Bitmap.Config.RGB_565 -> if (options.allowRgb565) PreferredColorConfig.RGB_565 else PreferredColorConfig.DEFAULT - Bitmap.Config.ARGB_8888 -> PreferredColorConfig.RGBA_8888 - else -> PreferredColorConfig.DEFAULT - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && options.config == Bitmap.Config.RGBA_F16) { - mPreferredColorConfig = PreferredColorConfig.RGBA_F16 - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && options.config == Bitmap.Config.HARDWARE) { - mPreferredColorConfig = PreferredColorConfig.HARDWARE - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && options.config == Bitmap.Config.RGBA_1010102) { - mPreferredColorConfig = PreferredColorConfig.RGBA_1010102 - } - - if (options.size == coil.size.Size.ORIGINAL) { - val originalImage = - coder.decode( - sourceData, - preferredColorConfig = mPreferredColorConfig - ) - return@runInterruptible DecodeResult( - BitmapDrawable( - options.context.resources, - originalImage - ), false - ) - } - - val dstWidth = options.size.width.pxOrElse { 0 } - val dstHeight = options.size.height.pxOrElse { 0 } - val scaleMode = when (options.scale) { - Scale.FILL -> ScaleMode.FILL - Scale.FIT -> ScaleMode.FIT - } - - val originalImage = - coder.decodeSampled( - sourceData, - dstWidth, - dstHeight, - preferredColorConfig = mPreferredColorConfig, - scaleMode, - ) - return@runInterruptible DecodeResult( - BitmapDrawable( - options.context.resources, - originalImage - ), true - ) - } catch (e: Exception) { - exceptionLogger?.invoke(e) - return@runInterruptible null - } - } - - class Factory : Decoder.Factory { - override fun create( - result: SourceResult, - options: Options, - imageLoader: ImageLoader - ): Decoder? { - return if (AVAILABLE_BRANDS.any { - result.source.source().rangeEquals(4, it) - }) HeifDecoderCoil2(result, options) else null - } - - companion object { - private val MIF = "ftypmif1".encodeUtf8() - private val MSF = "ftypmsf1".encodeUtf8() - private val HEIC = "ftypheic".encodeUtf8() - private val HEIX = "ftypheix".encodeUtf8() - private val HEVC = "ftyphevc".encodeUtf8() - private val HEVX = "ftyphevx".encodeUtf8() - private val AVIF = "ftypavif".encodeUtf8() - private val AVIS = "ftypavis".encodeUtf8() - - private val AVAILABLE_BRANDS = listOf(MIF, MSF, HEIC, HEIX, HEVC, HEVX, AVIF, AVIS) - } - } -} \ No newline at end of file diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/TimeMeasureInterceptor.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/TimeMeasureInterceptor.kt index 169fd74cc..cdac15bf4 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/TimeMeasureInterceptor.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/coil/TimeMeasureInterceptor.kt @@ -17,8 +17,9 @@ package ru.tech.imageresizershrinker.core.data.coil -import coil.intercept.Interceptor -import coil.request.ImageResult +import coil3.intercept.Interceptor +import coil3.request.ImageResult +import coil3.request.transformations import com.t8rin.logger.makeLog import javax.inject.Inject @@ -28,7 +29,7 @@ internal class TimeMeasureInterceptor @Inject constructor() : Interceptor { chain: Interceptor.Chain ): ImageResult { val time = System.currentTimeMillis() - val result = chain.proceed(chain.request) + val result = chain.proceed() val endTime = System.currentTimeMillis() val delta = endTime - time diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/di/ImageLoaderModule.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/di/ImageLoaderModule.kt index 5e223431e..f6af9b595 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/di/ImageLoaderModule.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/di/ImageLoaderModule.kt @@ -19,16 +19,20 @@ package ru.tech.imageresizershrinker.core.data.di import android.content.Context import android.os.Build -import coil.Coil -import coil.ComponentRegistry -import coil.ImageLoader -import coil.decode.GifDecoder -import coil.decode.ImageDecoderDecoder -import coil.decode.SvgDecoder -import coil.imageLoader -import coil.util.DebugLogger -import coil.util.Logger +import coil3.ComponentRegistry +import coil3.ImageLoader +import coil3.SingletonImageLoader +import coil3.annotation.DelicateCoilApi +import coil3.gif.AnimatedImageDecoder +import coil3.gif.GifDecoder +import coil3.imageLoader +import coil3.request.allowHardware +import coil3.svg.SvgDecoder +import coil3.util.DebugLogger +import coil3.util.Logger +import com.awxkee.jxlcoder.coil.AnimatedJxlDecoder import com.gemalto.jp2.coil.Jpeg2000Decoder +import com.github.awxkee.avifcoil.decoder.HeifDecoder import com.t8rin.awebp.coil.AnimatedWebPDecoder import com.t8rin.djvu_coder.coil.DjvuDecoder import com.t8rin.psd.coil.PsdDecoder @@ -40,8 +44,6 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import oupson.apng.coil.AnimatedPngDecoder -import ru.tech.imageresizershrinker.core.data.coil.AnimatedJxlDecoderCoil2 -import ru.tech.imageresizershrinker.core.data.coil.HeifDecoderCoil2 import ru.tech.imageresizershrinker.core.data.coil.TimeMeasureInterceptor import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder import ru.tech.imageresizershrinker.core.resources.BuildConfig @@ -50,6 +52,7 @@ import ru.tech.imageresizershrinker.core.resources.BuildConfig @InstallIn(SingletonComponent::class) internal object ImageLoaderModule { + @OptIn(DelicateCoilApi::class) @Provides fun provideImageLoader( @ApplicationContext context: Context, @@ -58,13 +61,13 @@ internal object ImageLoaderModule { dispatchersHolder: DispatchersHolder ): ImageLoader = context.imageLoader.newBuilder() .components(componentRegistry) - .decoderDispatcher(dispatchersHolder.decodingDispatcher) - .fetcherDispatcher(dispatchersHolder.ioDispatcher) - .transformationDispatcher(dispatchersHolder.defaultDispatcher) + .coroutineContext(dispatchersHolder.defaultDispatcher) + .decoderCoroutineContext(dispatchersHolder.decodingDispatcher) + .fetcherCoroutineContext(dispatchersHolder.ioDispatcher) .allowHardware(false) .logger(logger) .build() - .also(Coil::setImageLoader) + .also(SingletonImageLoader::setUnsafe) @Provides fun provideCoilLogger(): Logger? = if (BuildConfig.DEBUG) DebugLogger() @@ -72,21 +75,20 @@ internal object ImageLoaderModule { @Provides fun provideComponentRegistry( - @ApplicationContext context: Context, interceptor: TimeMeasureInterceptor ): ComponentRegistry = ComponentRegistry.Builder() .apply { add(AnimatedPngDecoder.Factory()) - if (Build.VERSION.SDK_INT >= 28) add(ImageDecoderDecoder.Factory()) + if (Build.VERSION.SDK_INT >= 28) add(AnimatedImageDecoder.Factory()) else { add(GifDecoder.Factory()) add(AnimatedWebPDecoder.Factory()) } add(SvgDecoder.Factory()) if (Build.VERSION.SDK_INT >= 24) { - add(HeifDecoderCoil2.Factory()) + add(HeifDecoder.Factory()) } - add(AnimatedJxlDecoderCoil2.Factory(context)) + add(AnimatedJxlDecoder.Factory()) add(Jpeg2000Decoder.Factory()) add(TiffDecoder.Factory()) add(QoiDecoder.Factory()) diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageGetter.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageGetter.kt index 706e14798..ba7f1813d 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageGetter.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageGetter.kt @@ -26,15 +26,16 @@ import android.provider.MediaStore import android.webkit.MimeTypeMap import androidx.core.net.toUri import androidx.exifinterface.media.ExifInterface -import coil.ImageLoader -import coil.request.ImageRequest -import coil.size.Size +import coil3.ImageLoader +import coil3.request.ImageRequest +import coil3.request.transformations +import coil3.size.Size +import coil3.toBitmap import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.withContext -import ru.tech.imageresizershrinker.core.data.utils.toBitmap import ru.tech.imageresizershrinker.core.data.utils.toCoil import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder import ru.tech.imageresizershrinker.core.domain.image.ImageGetter @@ -106,7 +107,7 @@ internal class AndroidImageGetter @Inject constructor( if (originalSize) size(Size.ORIGINAL) } .build() - ).drawable?.toBitmap() + ).image?.toBitmap() }.getOrNull() } @@ -127,7 +128,7 @@ internal class AndroidImageGetter @Inject constructor( ) } .build() - ).drawable?.toBitmap() + ).image?.toBitmap() }.getOrNull() } @@ -146,7 +147,7 @@ internal class AndroidImageGetter @Inject constructor( } ?: size(Size.ORIGINAL) } .build() - ).drawable?.toBitmap() + ).image?.toBitmap() }.getOrNull() } @@ -167,7 +168,7 @@ internal class AndroidImageGetter @Inject constructor( .build() runCatching { - imageLoader.execute(request).drawable?.toBitmap()?.let { bitmap -> + imageLoader.execute(request).image?.toBitmap()?.let { bitmap -> val newUri = uri.toUri().tryGetLocation(context) val fd = context.contentResolver.openFileDescriptor(newUri, "r") val exif = fd?.fileDescriptor?.let { ExifInterface(it) } @@ -205,7 +206,7 @@ internal class AndroidImageGetter @Inject constructor( .build() runCatching { - imageLoader.execute(request).drawable?.toBitmap() + imageLoader.execute(request).image?.toBitmap() }.getOrNull() } diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageScaler.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageScaler.kt index eb708c1f6..c12b68235 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageScaler.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageScaler.kt @@ -18,9 +18,8 @@ package ru.tech.imageresizershrinker.core.data.image import android.graphics.Bitmap +import android.graphics.Color import android.graphics.PorterDuff -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.toArgb import androidx.core.graphics.BitmapCompat import androidx.core.graphics.applyCanvas import com.awxkee.aire.Aire @@ -234,7 +233,7 @@ internal class AndroidImageScaler @Inject constructor( ).apply { setHasAlpha(true) }.applyCanvas { - drawColor(Color.Transparent.toArgb(), PorterDuff.Mode.CLEAR) + drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) canvasColor?.let { drawColor(it) } ?: blurredBitmap?.let { @@ -320,7 +319,7 @@ internal class AndroidImageScaler @Inject constructor( ).apply { setHasAlpha(true) }.applyCanvas { - drawColor(Color.Transparent.toArgb(), PorterDuff.Mode.CLEAR) + drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) canvasColor?.let { drawColor(it) } ?: blurredBitmap?.let { diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageTransformer.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageTransformer.kt index 1258b99a5..7f38ecd87 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageTransformer.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/AndroidImageTransformer.kt @@ -20,12 +20,13 @@ package ru.tech.imageresizershrinker.core.data.image import android.content.Context import android.graphics.Bitmap import android.graphics.Matrix -import coil.ImageLoader -import coil.request.ImageRequest -import coil.size.Size +import coil3.ImageLoader +import coil3.request.ImageRequest +import coil3.request.transformations +import coil3.size.Size +import coil3.toBitmap import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.withContext -import ru.tech.imageresizershrinker.core.data.utils.toBitmap import ru.tech.imageresizershrinker.core.data.utils.toCoil import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder import ru.tech.imageresizershrinker.core.domain.image.ImageTransformer @@ -68,7 +69,7 @@ internal class AndroidImageTransformer @Inject constructor( } .build() - return@withContext imageLoader.execute(request).drawable?.toBitmap() + return@withContext imageLoader.execute(request).image?.toBitmap() } override suspend fun transform( @@ -89,7 +90,7 @@ internal class AndroidImageTransformer @Inject constructor( .size(size.width, size.height) .build() - return@withContext imageLoader.execute(request).drawable?.toBitmap() + return@withContext imageLoader.execute(request).image?.toBitmap() } override suspend fun applyPresetBy( @@ -105,7 +106,7 @@ internal class AndroidImageTransformer @Inject constructor( .data(it) .size(Size.ORIGINAL) .build() - ).drawable?.run { intrinsicWidth sizeTo intrinsicHeight } + ).image?.run { width sizeTo height } } ?: IntegerSize(image.width, image.height) val rotated = abs(currentInfo.rotationDegrees) % 180 != 0f diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/utils/BlendingModeExt.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/utils/BlendingModeExt.kt index e59030688..273ea37dc 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/utils/BlendingModeExt.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/image/utils/BlendingModeExt.kt @@ -19,7 +19,6 @@ package ru.tech.imageresizershrinker.core.data.image.utils import android.os.Build import androidx.annotation.RequiresApi -import androidx.compose.ui.graphics.BlendMode import ru.tech.imageresizershrinker.core.domain.image.model.BlendingMode import android.graphics.BlendMode as AndroidBlendMode import android.graphics.PorterDuff.Mode as PorterDuffMode @@ -52,7 +51,7 @@ fun BlendingMode.toPorterDuffMode(): PorterDuffMode = when (this) { } /** - * Convert the compose [BlendMode] to the underlying Android platform [AndroidBlendMode] + * Convert the domain [BlendingMode] to the underlying Android platform [AndroidBlendMode] */ @RequiresApi(Build.VERSION_CODES.Q) fun BlendingMode.toAndroidBlendMode(): AndroidBlendMode = when (this) { diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/BitmapUtils.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/BitmapUtils.kt index c878c184d..f96463fbe 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/BitmapUtils.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/BitmapUtils.kt @@ -20,7 +20,6 @@ package ru.tech.imageresizershrinker.core.data.utils import android.graphics.Bitmap import android.graphics.drawable.Drawable import android.os.Build -import androidx.compose.ui.graphics.ImageBitmap import androidx.core.graphics.drawable.toBitmap import java.io.ByteArrayOutputStream @@ -45,8 +44,6 @@ fun Bitmap.toSoftware(): Bitmap = copy(getSuitableConfig(this), false) ?: this val Bitmap.aspectRatio: Float get() = width / height.toFloat() -val ImageBitmap.aspectRatio: Float get() = width / height.toFloat() - val Drawable.aspectRatio: Float get() = intrinsicWidth / intrinsicHeight.toFloat() val Bitmap.safeAspectRatio: Float @@ -57,11 +54,6 @@ val Bitmap.safeAspectRatio: Float val Bitmap.safeConfig: Bitmap.Config get() = config ?: getSuitableConfig(this) -val ImageBitmap.safeAspectRatio: Float - get() = aspectRatio - .coerceAtLeast(0.005f) - .coerceAtMost(1000f) - val Drawable.safeAspectRatio: Float get() = aspectRatio .coerceAtLeast(0.005f) diff --git a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/CoilUtils.kt b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/CoilUtils.kt index f267a6773..91b91d901 100644 --- a/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/CoilUtils.kt +++ b/core/data/src/main/java/ru/tech/imageresizershrinker/core/data/utils/CoilUtils.kt @@ -18,11 +18,11 @@ package ru.tech.imageresizershrinker.core.data.utils import android.graphics.Bitmap -import coil.size.Size -import coil.size.pxOrElse +import coil3.size.Size +import coil3.size.pxOrElse import ru.tech.imageresizershrinker.core.domain.model.IntegerSize import ru.tech.imageresizershrinker.core.domain.transformation.Transformation -import coil.transform.Transformation as CoilTransformation +import coil3.transform.Transformation as CoilTransformation fun Size.asDomain(): IntegerSize = if (this == Size.ORIGINAL) IntegerSize.Undefined else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 }) @@ -30,7 +30,7 @@ else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 }) fun IntegerSize.asCoil(): Size = if (this == IntegerSize.Undefined) Size.ORIGINAL else Size(width, height) -fun Transformation.toCoil(): CoilTransformation = object : CoilTransformation { +fun Transformation.toCoil(): CoilTransformation = object : CoilTransformation() { private val instance = this@toCoil override fun toString(): String = instance::class.simpleName.toString() diff --git a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/AddFiltersSheet.kt b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/AddFiltersSheet.kt index dfd580bb2..02bc85ecf 100644 --- a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/AddFiltersSheet.kt +++ b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/AddFiltersSheet.kt @@ -115,7 +115,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.net.toUri import androidx.exifinterface.media.ExifInterface -import coil.transform.Transformation +import coil3.transform.Transformation import com.arkivanov.decompose.ComponentContext import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterSelectionItem.kt b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterSelectionItem.kt index afc08377f..e63432a24 100644 --- a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterSelectionItem.kt +++ b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterSelectionItem.kt @@ -89,9 +89,12 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest -import coil.transform.Transformation +import coil3.compose.rememberAsyncImagePainter +import coil3.request.ImageRequest +import coil3.request.error +import coil3.request.transformations +import coil3.toBitmap +import coil3.transform.Transformation import kotlinx.coroutines.launch import ru.tech.imageresizershrinker.core.domain.model.FileModel import ru.tech.imageresizershrinker.core.domain.model.ImageModel @@ -106,7 +109,6 @@ import ru.tech.imageresizershrinker.core.ui.theme.StrongBlack import ru.tech.imageresizershrinker.core.ui.theme.White import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.isNetworkAvailable -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedAlertDialog import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton @@ -172,7 +174,7 @@ internal fun FilterSelectionItem( onSuccess = { loading = false scope.launch { - isBitmapDark = calculateBrightnessEstimate(it.result.drawable.toBitmap()) < 110 + isBitmapDark = calculateBrightnessEstimate(it.result.image.toBitmap()) < 110 } } ) diff --git a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterTemplateInfoSheet.kt b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterTemplateInfoSheet.kt index 53959e880..6704c7efb 100644 --- a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterTemplateInfoSheet.kt +++ b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/FilterTemplateInfoSheet.kt @@ -73,9 +73,11 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.min import androidx.compose.ui.unit.sp -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest -import coil.transform.Transformation +import coil3.compose.rememberAsyncImagePainter +import coil3.request.ImageRequest +import coil3.request.error +import coil3.request.transformations +import coil3.transform.Transformation import dev.shreyaspatil.capturable.capturable import dev.shreyaspatil.capturable.controller.rememberCaptureController import kotlinx.coroutines.launch diff --git a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/TemplateFilterSelectionItem.kt b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/TemplateFilterSelectionItem.kt index 75692fec0..22956d4ca 100644 --- a/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/TemplateFilterSelectionItem.kt +++ b/core/filters/src/main/java/ru/tech/imageresizershrinker/core/filters/presentation/widget/TemplateFilterSelectionItem.kt @@ -51,9 +51,12 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest -import coil.transform.Transformation +import coil3.compose.rememberAsyncImagePainter +import coil3.request.ImageRequest +import coil3.request.error +import coil3.request.transformations +import coil3.toBitmap +import coil3.transform.Transformation import kotlinx.coroutines.launch import ru.tech.imageresizershrinker.core.domain.model.ImageModel import ru.tech.imageresizershrinker.core.filters.domain.model.TemplateFilter @@ -63,7 +66,6 @@ import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.ui.theme.StrongBlack import ru.tech.imageresizershrinker.core.ui.theme.White import ru.tech.imageresizershrinker.core.ui.theme.outlineVariant -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.toImageModel import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer @@ -108,7 +110,7 @@ internal fun TemplateFilterSelectionItem( onSuccess = { loading = false scope.launch { - isBitmapDark = calculateBrightnessEstimate(it.result.drawable.toBitmap()) < 110 + isBitmapDark = calculateBrightnessEstimate(it.result.image.toBitmap()) < 110 } } ) diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index aec6a6afd..419794a09 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -49,6 +49,8 @@ dependencies { api(libs.coilCompose) api(libs.coilGif) api(libs.coilSvg) + api(libs.coilNetwork) + api(libs.ktor) //Modules api(libs.toolbox.uCrop) @@ -71,7 +73,7 @@ dependencies { api(libs.reorderable) - api(libs.compose) + api(libs.shadowGadgets) api(libs.shadowsPlus) api(libs.kotlinx.collections.immutable) diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/transformation/ImageInfoTransformation.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/transformation/ImageInfoTransformation.kt index 0038a89a1..23759f158 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/transformation/ImageInfoTransformation.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/transformation/ImageInfoTransformation.kt @@ -18,8 +18,8 @@ package ru.tech.imageresizershrinker.core.ui.transformation import android.graphics.Bitmap -import coil.size.Size -import coil.size.pxOrElse +import coil3.size.Size +import coil3.size.pxOrElse import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject @@ -35,7 +35,7 @@ import ru.tech.imageresizershrinker.core.domain.model.IntegerSize import ru.tech.imageresizershrinker.core.domain.transformation.Transformation import ru.tech.imageresizershrinker.core.ui.utils.helper.asCoil import kotlin.math.roundToInt -import coil.transform.Transformation as CoilTransformation +import coil3.transform.Transformation as CoilTransformation class ImageInfoTransformation @AssistedInject internal constructor( @Assisted private val imageInfo: ImageInfo, @@ -45,7 +45,7 @@ class ImageInfoTransformation @AssistedInject internal constructor( private val imageScaler: ImageScaler, private val imagePreviewCreator: ImagePreviewCreator, private val shareProvider: ShareProvider -) : CoilTransformation, Transformation { +) : CoilTransformation(), Transformation { override val cacheKey: String get() = Triple(imageInfo, preset, transformations).hashCode().toString() diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/helper/CoilUtils.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/helper/CoilUtils.kt index bd4a5378a..75afc2191 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/helper/CoilUtils.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/helper/CoilUtils.kt @@ -18,11 +18,11 @@ package ru.tech.imageresizershrinker.core.ui.utils.helper import android.graphics.Bitmap -import coil.size.Size -import coil.size.pxOrElse +import coil3.size.Size +import coil3.size.pxOrElse import ru.tech.imageresizershrinker.core.domain.model.IntegerSize import ru.tech.imageresizershrinker.core.domain.transformation.Transformation -import coil.transform.Transformation as CoilTransformation +import coil3.transform.Transformation as CoilTransformation fun Size.asDomain(): IntegerSize = if (this == Size.ORIGINAL) IntegerSize.Undefined else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 }) @@ -30,7 +30,7 @@ else IntegerSize(width.pxOrElse { 1 }, height.pxOrElse { 1 }) fun IntegerSize.asCoil(): Size = if (this == IntegerSize.Undefined) Size.ORIGINAL else Size(width, height) -fun Transformation.toCoil(): CoilTransformation = object : CoilTransformation { +fun Transformation.toCoil(): CoilTransformation = object : CoilTransformation() { private val instance = this@toCoil override fun toString(): String = instance::class.simpleName.toString() diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/provider/LocalImageLoader.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/provider/LocalImageLoader.kt index 5057e2690..c8f80040e 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/provider/LocalImageLoader.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/utils/provider/LocalImageLoader.kt @@ -18,6 +18,6 @@ package ru.tech.imageresizershrinker.core.ui.utils.provider import androidx.compose.runtime.compositionLocalOf -import coil.ImageLoader +import coil3.ImageLoader val LocalImageLoader = compositionLocalOf { error("No ImageLoader provided") } \ No newline at end of file diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/Picture.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/Picture.kt index 9afdcb5c4..7b377e16d 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/Picture.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/Picture.kt @@ -39,13 +39,16 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext -import androidx.core.graphics.drawable.toBitmapOrNull -import coil.ImageLoader -import coil.compose.AsyncImagePainter -import coil.compose.SubcomposeAsyncImage -import coil.compose.SubcomposeAsyncImageScope -import coil.request.ImageRequest -import coil.transform.Transformation +import coil3.ImageLoader +import coil3.compose.AsyncImagePainter +import coil3.compose.SubcomposeAsyncImage +import coil3.compose.SubcomposeAsyncImageScope +import coil3.request.ImageRequest +import coil3.request.allowHardware +import coil3.request.crossfade +import coil3.request.transformations +import coil3.toBitmap +import coil3.transform.Transformation import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.withContext @@ -155,7 +158,7 @@ fun Picture( onSuccess = { if (model is ImageRequest && Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE && enableUltraHDRSupport) { activity.window.colorMode = - if (it.result.drawable.toBitmapOrNull(400, 400)?.hasGainmap() == true) { + if (it.result.image.toBitmap(400, 400).hasGainmap()) { ActivityInfo.COLOR_MODE_HDR } else ActivityInfo.COLOR_MODE_DEFAULT } diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/UrisCarousel.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/UrisCarousel.kt index c835122b3..8daf3601d 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/UrisCarousel.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/image/UrisCarousel.kt @@ -44,7 +44,9 @@ import androidx.compose.ui.layout.layout import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach -import coil.request.ImageRequest +import coil3.asDrawable +import coil3.request.ImageRequest +import coil3.request.crossfade import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio import ru.tech.imageresizershrinker.core.ui.widget.modifier.container import kotlin.math.roundToInt @@ -100,7 +102,7 @@ internal fun UrisCarousel(uris: List) { .build() }, onSuccess = { - aspectRatio = it.result.drawable.safeAspectRatio + aspectRatio = it.result.image.asDrawable(context.resources).safeAspectRatio }, modifier = Modifier .animateContentSize() diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/other/EmojiItem.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/other/EmojiItem.kt index 11eefd426..c3a2fd382 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/other/EmojiItem.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/other/EmojiItem.kt @@ -46,8 +46,9 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp -import coil.compose.rememberAsyncImagePainter -import coil.request.ImageRequest +import coil3.compose.rememberAsyncImagePainter +import coil3.request.ImageRequest +import coil3.request.crossfade import ru.tech.imageresizershrinker.core.ui.shapes.CloverShape import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalImageLoader import ru.tech.imageresizershrinker.core.ui.widget.modifier.shimmer diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/PickImageFromUrisSheet.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/PickImageFromUrisSheet.kt index a8137f612..c2c5065ab 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/PickImageFromUrisSheet.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/PickImageFromUrisSheet.kt @@ -52,7 +52,7 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.transform.Transformation +import coil3.transform.Transformation import ru.tech.imageresizershrinker.core.domain.utils.notNullAnd import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton diff --git a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/ZoomModalSheet.kt b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/ZoomModalSheet.kt index ea8e781b3..6ec1ca26e 100644 --- a/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/ZoomModalSheet.kt +++ b/core/ui/src/main/kotlin/ru/tech/imageresizershrinker/core/ui/widget/sheets/ZoomModalSheet.kt @@ -17,6 +17,7 @@ package ru.tech.imageresizershrinker.core.ui.widget.sheets +import android.content.res.Resources import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.scaleIn @@ -50,7 +51,8 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.transform.Transformation +import coil3.asDrawable +import coil3.transform.Transformation import com.smarttoolfactory.colordetector.util.ColorUtil.roundToTwoDigits import net.engawapg.lib.zoomable.rememberZoomState import net.engawapg.lib.zoomable.zoomable @@ -107,7 +109,8 @@ fun ZoomModalSheet( model = data, contentDescription = null, onSuccess = { - aspectRatio = it.result.drawable.safeAspectRatio + aspectRatio = + it.result.image.asDrawable(Resources.getSystem()).safeAspectRatio }, contentScale = ContentScale.FillBounds, showTransparencyChecker = false, diff --git a/feature/draw/src/main/java/ru/tech/imageresizershrinker/feature/draw/presentation/components/utils/DrawUtils.kt b/feature/draw/src/main/java/ru/tech/imageresizershrinker/feature/draw/presentation/components/utils/DrawUtils.kt index 4a4db5415..11f62d93e 100644 --- a/feature/draw/src/main/java/ru/tech/imageresizershrinker/feature/draw/presentation/components/utils/DrawUtils.kt +++ b/feature/draw/src/main/java/ru/tech/imageresizershrinker/feature/draw/presentation/components/utils/DrawUtils.kt @@ -57,12 +57,12 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import androidx.core.content.res.ResourcesCompat import androidx.core.graphics.applyCanvas -import coil.request.ImageRequest +import coil3.request.ImageRequest +import coil3.toBitmap import ru.tech.imageresizershrinker.core.data.utils.safeConfig import ru.tech.imageresizershrinker.core.domain.model.IntegerSize import ru.tech.imageresizershrinker.core.domain.model.Pt import ru.tech.imageresizershrinker.core.ui.shapes.MaterialStarShape -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.provider.LocalImageLoader import ru.tech.imageresizershrinker.feature.draw.domain.DrawLineStyle import ru.tech.imageresizershrinker.feature.draw.domain.DrawMode @@ -347,7 +347,7 @@ fun NativeCanvas.drawRepeatedImageOnPath( .data(drawMode.imageData) .size(strokeWidth.toPx(canvasSize).roundToInt()) .build() - ).drawable?.toBitmap() + ).image?.toBitmap() } } pathImage?.let { bitmap -> diff --git a/feature/filters/src/main/java/ru/tech/imageresizershrinker/feature/filters/data/model/GPUFilterTransformation.kt b/feature/filters/src/main/java/ru/tech/imageresizershrinker/feature/filters/data/model/GPUFilterTransformation.kt index 142c624c8..d18011501 100644 --- a/feature/filters/src/main/java/ru/tech/imageresizershrinker/feature/filters/data/model/GPUFilterTransformation.kt +++ b/feature/filters/src/main/java/ru/tech/imageresizershrinker/feature/filters/data/model/GPUFilterTransformation.kt @@ -19,8 +19,8 @@ package ru.tech.imageresizershrinker.feature.filters.data.model import android.content.Context import android.graphics.Bitmap -import coil.size.Size -import coil.size.pxOrElse +import coil3.size.Size +import coil3.size.pxOrElse import jp.co.cyberagent.android.gpuimage.GPUImage import jp.co.cyberagent.android.gpuimage.filter.GPUImageFilter import ru.tech.imageresizershrinker.core.data.utils.asCoil @@ -28,11 +28,11 @@ import ru.tech.imageresizershrinker.core.data.utils.aspectRatio import ru.tech.imageresizershrinker.core.domain.model.IntegerSize import ru.tech.imageresizershrinker.core.domain.transformation.Transformation import java.lang.Integer.max -import coil.transform.Transformation as CoilTransformation +import coil3.transform.Transformation as CoilTransformation internal abstract class GPUFilterTransformation( private val context: Context, -) : CoilTransformation, Transformation { +) : CoilTransformation(), Transformation { /** * Create the [GPUImageFilter] to apply to this [Transformation] diff --git a/feature/gradient-maker/src/main/java/ru/tech/imageresizershrinker/feature/gradient_maker/presentation/screenLogic/GradientMakerComponent.kt b/feature/gradient-maker/src/main/java/ru/tech/imageresizershrinker/feature/gradient_maker/presentation/screenLogic/GradientMakerComponent.kt index 909ee98bd..41ff6fe41 100644 --- a/feature/gradient-maker/src/main/java/ru/tech/imageresizershrinker/feature/gradient_maker/presentation/screenLogic/GradientMakerComponent.kt +++ b/feature/gradient-maker/src/main/java/ru/tech/imageresizershrinker/feature/gradient_maker/presentation/screenLogic/GradientMakerComponent.kt @@ -31,7 +31,7 @@ import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.graphics.TileMode import androidx.core.net.toUri import androidx.exifinterface.media.ExifInterface -import coil.transform.Transformation +import coil3.transform.Transformation import com.arkivanov.decompose.ComponentContext import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/feature/image-preview/src/main/java/ru/tech/imageresizershrinker/feature/image_preview/presentation/components/ImagePreviewGrid.kt b/feature/image-preview/src/main/java/ru/tech/imageresizershrinker/feature/image_preview/presentation/components/ImagePreviewGrid.kt index 562eb134d..412eb5cdf 100644 --- a/feature/image-preview/src/main/java/ru/tech/imageresizershrinker/feature/image_preview/presentation/components/ImagePreviewGrid.kt +++ b/feature/image-preview/src/main/java/ru/tech/imageresizershrinker/feature/image_preview/presentation/components/ImagePreviewGrid.kt @@ -47,11 +47,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.net.toUri -import coil.request.ImageRequest +import coil3.request.ImageRequest +import coil3.toBitmap import com.t8rin.modalsheet.FullscreenPopup import ru.tech.imageresizershrinker.core.domain.image.model.ImageFrames import ru.tech.imageresizershrinker.core.resources.R -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker import ru.tech.imageresizershrinker.core.ui.utils.helper.rememberImagePicker import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen @@ -191,7 +191,7 @@ internal fun ImagePreviewGrid( ImageRequest.Builder(context) .data(uri.toUri()) .build() - ).drawable?.toBitmap() + ).image?.toBitmap() } ) } \ No newline at end of file diff --git a/feature/image-splitting/src/main/java/ru/tech/imageresizershrinker/image_splitting/presentation/ImageSplitterContent.kt b/feature/image-splitting/src/main/java/ru/tech/imageresizershrinker/image_splitting/presentation/ImageSplitterContent.kt index 070aa759f..cf6b1c5e1 100644 --- a/feature/image-splitting/src/main/java/ru/tech/imageresizershrinker/image_splitting/presentation/ImageSplitterContent.kt +++ b/feature/image-splitting/src/main/java/ru/tech/imageresizershrinker/image_splitting/presentation/ImageSplitterContent.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import coil3.toBitmap import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker @@ -119,7 +120,7 @@ fun ImageSplitterContent( .padding(4.dp) .clip(MaterialTheme.shapes.medium), onSuccess = { - aspectRatio = it.result.drawable.safeAspectRatio + aspectRatio = it.result.image.toBitmap().safeAspectRatio } ) } else { diff --git a/feature/load-net-image/src/main/java/ru/tech/imageresizershrinker/feature/load_net_image/presentation/LoadNetImageContent.kt b/feature/load-net-image/src/main/java/ru/tech/imageresizershrinker/feature/load_net_image/presentation/LoadNetImageContent.kt index 1fa476c8d..0f3a8c144 100644 --- a/feature/load-net-image/src/main/java/ru/tech/imageresizershrinker/feature/load_net_image/presentation/LoadNetImageContent.kt +++ b/feature/load-net-image/src/main/java/ru/tech/imageresizershrinker/feature/load_net_image/presentation/LoadNetImageContent.kt @@ -48,11 +48,11 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import coil.compose.AsyncImagePainter +import coil3.compose.AsyncImagePainter +import coil3.toBitmap import ru.tech.imageresizershrinker.core.domain.image.model.ImageInfo import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.icons.ImageEdit -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip import ru.tech.imageresizershrinker.core.ui.utils.helper.isLandscapeOrientationAsState import ru.tech.imageresizershrinker.core.ui.utils.navigation.Screen @@ -212,7 +212,7 @@ fun LoadNetImageContent( if (it is AsyncImagePainter.State.Error) { component.updateBitmap(null) } else if (it is AsyncImagePainter.State.Success) { - component.updateBitmap(it.result.drawable.toBitmap()) + component.updateBitmap(it.result.image.toBitmap()) } imageState = it }, diff --git a/feature/media-picker/src/main/java/ru/tech/imageresizershrinker/feature/media_picker/presentation/screenLogic/MediaPickerComponent.kt b/feature/media-picker/src/main/java/ru/tech/imageresizershrinker/feature/media_picker/presentation/screenLogic/MediaPickerComponent.kt index cfa5ad852..4587ddacb 100644 --- a/feature/media-picker/src/main/java/ru/tech/imageresizershrinker/feature/media_picker/presentation/screenLogic/MediaPickerComponent.kt +++ b/feature/media-picker/src/main/java/ru/tech/imageresizershrinker/feature/media_picker/presentation/screenLogic/MediaPickerComponent.kt @@ -21,7 +21,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.exifinterface.media.ExifInterface -import coil.ImageLoader +import coil3.ImageLoader import com.arkivanov.decompose.ComponentContext import com.t8rin.dynamic.theme.ColorTuple import com.t8rin.dynamic.theme.extractPrimaryColor diff --git a/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/data/AndroidPdfManager.kt b/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/data/AndroidPdfManager.kt index 5aae92644..1fd66d418 100644 --- a/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/data/AndroidPdfManager.kt +++ b/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/data/AndroidPdfManager.kt @@ -26,9 +26,10 @@ import android.graphics.pdf.PdfRenderer import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.core.net.toUri -import coil.ImageLoader -import coil.request.ImageRequest -import coil.size.Size +import coil3.ImageLoader +import coil3.request.ImageRequest +import coil3.size.Size +import coil3.toBitmap import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay @@ -36,7 +37,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import ru.tech.imageresizershrinker.core.data.utils.aspectRatio import ru.tech.imageresizershrinker.core.data.utils.getSuitableConfig -import ru.tech.imageresizershrinker.core.data.utils.toBitmap import ru.tech.imageresizershrinker.core.domain.dispatchers.DispatchersHolder import ru.tech.imageresizershrinker.core.domain.image.ImageScaler import ru.tech.imageresizershrinker.core.domain.image.model.ImageScaleMode @@ -186,12 +186,12 @@ internal class AndroidPdfManager @Inject constructor( val r = PdfRenderer(fileDescriptor) List(r.pageCount) { val page = r.openPage(it) - page?.run { + page.run { IntegerSize(width, height) }.also { page.close() } - }.filterNotNull().also { + }.also { pagesBuf[uri] = it } } @@ -217,7 +217,7 @@ internal class AndroidPdfManager @Inject constructor( .data(uri) .size(Size.ORIGINAL) .build() - ).drawable?.toBitmap()?.let { + ).image?.toBitmap()?.let { imageScaler.scaleImage( image = it, width = (it.width * percent / 100f).roundToInt(), diff --git a/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/presentation/components/PdfViewer.kt b/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/presentation/components/PdfViewer.kt index 08dc5e69c..b9d271819 100644 --- a/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/presentation/components/PdfViewer.kt +++ b/feature/pdf-tools/src/main/java/ru/tech/imageresizershrinker/feature/pdf_tools/presentation/components/PdfViewer.kt @@ -90,8 +90,10 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.compose.LocalLifecycleOwner -import coil.memory.MemoryCache -import coil.request.ImageRequest +import coil3.Image +import coil3.asImage +import coil3.memory.MemoryCache +import coil3.request.ImageRequest import com.t8rin.dynamic.theme.observeAsState import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay @@ -477,9 +479,9 @@ private fun PdfPage( val imageLoader = LocalImageLoader.current val imageLoadingScope = rememberCoroutineScope() - val cacheValue: Bitmap? = imageLoader.memoryCache?.get(cacheKey)?.bitmap + val cacheValue: Image? = imageLoader.memoryCache?.get(cacheKey)?.image - var bitmap: Bitmap? by remember { mutableStateOf(cacheValue) } + var bitmap: Image? by remember { mutableStateOf(cacheValue) } if (bitmap == null) { DisposableEffect(cacheKey, index) { val job = imageLoadingScope.launch(Dispatchers.IO) { @@ -503,7 +505,7 @@ private fun PdfPage( null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY ) - bitmap = destinationBitmap + bitmap = destinationBitmap.asImage() } } } catch (e: Exception) { @@ -518,11 +520,13 @@ private fun PdfPage( } } - val request = ImageRequest.Builder(context) - .size(renderWidth, renderHeight) - .memoryCacheKey(cacheKey) - .data(bitmap) - .build() + val request = remember(context, renderWidth, renderHeight, bitmap) { + ImageRequest.Builder(context) + .size(renderWidth, renderHeight) + .memoryCacheKey(cacheKey) + .data(bitmap) + .build() + } val transition = updateTransition(selected) val padding by transition.animateDp { s -> diff --git a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/domain/TessParams.kt b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/domain/TessParams.kt index dab74baa6..e9c48b45c 100644 --- a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/domain/TessParams.kt +++ b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/domain/TessParams.kt @@ -17,7 +17,7 @@ package ru.tech.imageresizershrinker.feature.recognize.text.domain -import okhttp3.internal.toImmutableList +import kotlinx.collections.immutable.toImmutableList import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_CHOP_ENABLE import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_EDGES_MAX_CHILDREN_PER_OUTLINE import ru.tech.imageresizershrinker.feature.recognize.text.domain.Constants.KEY_ENABLE_NEW_SEGSEARCH diff --git a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/RecognizeTextContent.kt b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/RecognizeTextContent.kt index e630091e8..86d3be896 100644 --- a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/RecognizeTextContent.kt +++ b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/RecognizeTextContent.kt @@ -49,7 +49,8 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.request.ImageRequest +import coil3.request.ImageRequest +import coil3.toBitmap import ru.tech.imageresizershrinker.core.domain.utils.notNullAnd import ru.tech.imageresizershrinker.core.domain.utils.readableByteCount import ru.tech.imageresizershrinker.core.resources.R @@ -60,7 +61,6 @@ import ru.tech.imageresizershrinker.core.ui.utils.helper.ContextUtils.copyToClip import ru.tech.imageresizershrinker.core.ui.utils.helper.FileType import ru.tech.imageresizershrinker.core.ui.utils.helper.ImagePickerMode import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.safeAspectRatio -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState import ru.tech.imageresizershrinker.core.ui.utils.helper.localImagePickerMode @@ -148,7 +148,7 @@ fun RecognizeTextContent( selector = { imageLoader.execute( ImageRequest.Builder(context).data(it).build() - ).drawable?.toBitmap() + ).image?.toBitmap() } ) diff --git a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/screenLogic/RecognizeTextComponent.kt b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/screenLogic/RecognizeTextComponent.kt index 61a7addcf..6b3f9c193 100644 --- a/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/screenLogic/RecognizeTextComponent.kt +++ b/feature/recognize-text/src/main/java/ru/tech/imageresizershrinker/feature/recognize/text/presentation/screenLogic/RecognizeTextComponent.kt @@ -70,7 +70,7 @@ import ru.tech.imageresizershrinker.feature.recognize.text.domain.TextRecognitio import java.text.SimpleDateFormat import java.util.Date import java.util.Locale -import coil.transform.Transformation as CoilTransformation +import coil3.transform.Transformation as CoilTransformation class RecognizeTextComponent @AssistedInject internal constructor( @Assisted componentContext: ComponentContext, diff --git a/feature/root/src/main/java/ru/tech/imageresizershrinker/feature/root/presentation/screenLogic/RootComponent.kt b/feature/root/src/main/java/ru/tech/imageresizershrinker/feature/root/presentation/screenLogic/RootComponent.kt index a1dbd5979..a7abd5c60 100644 --- a/feature/root/src/main/java/ru/tech/imageresizershrinker/feature/root/presentation/screenLogic/RootComponent.kt +++ b/feature/root/src/main/java/ru/tech/imageresizershrinker/feature/root/presentation/screenLogic/RootComponent.kt @@ -23,7 +23,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.graphics.vector.ImageVector import androidx.exifinterface.media.ExifInterface -import coil.ImageLoader +import coil3.ImageLoader import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.DelicateDecomposeApi import com.arkivanov.decompose.router.stack.ChildStack diff --git a/feature/single-edit/src/main/java/ru/tech/imageresizershrinker/feature/single_edit/presentation/components/FilterEditOption.kt b/feature/single-edit/src/main/java/ru/tech/imageresizershrinker/feature/single_edit/presentation/components/FilterEditOption.kt index 7ebcfad7a..c26fabee7 100644 --- a/feature/single-edit/src/main/java/ru/tech/imageresizershrinker/feature/single_edit/presentation/components/FilterEditOption.kt +++ b/feature/single-edit/src/main/java/ru/tech/imageresizershrinker/feature/single_edit/presentation/components/FilterEditOption.kt @@ -67,6 +67,7 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import coil3.toBitmap import kotlinx.coroutines.launch import net.engawapg.lib.zoomable.rememberZoomState import net.engawapg.lib.zoomable.zoomable @@ -80,7 +81,6 @@ import ru.tech.imageresizershrinker.core.filters.presentation.widget.FilterReord import ru.tech.imageresizershrinker.core.filters.presentation.widget.FilterTemplateCreationSheetComponent import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.ui.theme.mixedContainer -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedFloatingActionButton import ru.tech.imageresizershrinker.core.ui.widget.enhanced.EnhancedIconButton @@ -292,7 +292,7 @@ fun FilterEditOption( } }.value, onSuccess = { - stateBitmap = it.result.drawable.toBitmap() + stateBitmap = it.result.image.toBitmap() }, showTransparencyChecker = false, modifier = Modifier diff --git a/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/WatermarkingContent.kt b/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/WatermarkingContent.kt index 309126d4c..088cfa033 100644 --- a/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/WatermarkingContent.kt +++ b/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/WatermarkingContent.kt @@ -32,10 +32,10 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.request.ImageRequest +import coil3.request.ImageRequest +import coil3.toBitmap import ru.tech.imageresizershrinker.core.resources.R import ru.tech.imageresizershrinker.core.resources.icons.ImageReset -import ru.tech.imageresizershrinker.core.ui.utils.helper.ImageUtils.toBitmap import ru.tech.imageresizershrinker.core.ui.utils.helper.Picker import ru.tech.imageresizershrinker.core.ui.utils.helper.asClip import ru.tech.imageresizershrinker.core.ui.utils.helper.isPortraitOrientationAsState @@ -94,7 +94,7 @@ fun WatermarkingContent( selector = { imageLoader.execute( ImageRequest.Builder(context).data(it).build() - ).drawable?.toBitmap() + ).image?.toBitmap() } ) diff --git a/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/screenLogic/WatermarkingComponent.kt b/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/screenLogic/WatermarkingComponent.kt index ba54058e9..7d4720d1b 100644 --- a/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/screenLogic/WatermarkingComponent.kt +++ b/feature/watermarking/src/main/java/ru/tech/imageresizershrinker/feature/watermarking/presentation/screenLogic/WatermarkingComponent.kt @@ -25,7 +25,7 @@ import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.core.net.toUri import androidx.exifinterface.media.ExifInterface -import coil.transform.Transformation +import coil3.transform.Transformation import com.arkivanov.decompose.ComponentContext import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 760dac693..feb50ada6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,16 +7,15 @@ versionName = "3.1.0-rc01" versionCode = "156" jvmTarget = "17" -compose-compiler = "1.5.15" -imageToolboxLibs = "3.0.1" +imageToolboxLibs = "3.1.1" trickle = "1.2.2" avifCoder = "2.0.8" avifCoderCoil = "2.0.8" aire = "0.15.4" -jxlCoder = "2.4.0" -jxlCoderCoil = "2.4.0" +jxlCoder = "2.4.0.1" +jxlCoderCoil = "2.4.0.1" jpegliCoder = "1.0.1" tesseract = "4.7.0" @@ -40,12 +39,13 @@ detekt = "1.23.7" detektCompose = "0.4.18" decompose = "3.2.2" -kotlin = "1.9.25" +kotlin = "2.0.21" agp = "8.7.2" hilt = "2.52" gms = "4.4.2" -coil = "2.7.0" +ktor = "3.0.1" +coil = "3.0.2" appCompat = "1.7.0" androidxCore = "1.15.0" androidxLifecycle = "2.9.0-alpha07" @@ -58,13 +58,13 @@ reviewKtx = "2.0.2" splashScreen = "1.2.0-alpha02" espresso = "3.6.1" -ksp = "1.9.25-1.0.20" +ksp = "2.0.21-1.0.27" androidx-test-ext-junit = "1.2.1" documentfile = "1.0.1" uiautomator = "2.3.0" androidxMacroBenchmark = "1.4.0-alpha05" -quickie = "1.12.4" +quickie = "1.13.0" material = "1.13.0-alpha07" jsoup = "1.18.1" @@ -128,13 +128,14 @@ androidx-exifinterface = { module = "androidx.exifinterface:exifinterface", vers androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" } androidx-material3-window-sizeclass = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "material3" } androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" } +androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "composeVersion" } androidx-material = { module = "androidx.compose.material:material", version.ref = "composeVersion" } androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" } app-update-ktx = { module = "com.google.android.play:app-update-ktx", version.ref = "appUpdateKtx" } app-update = { module = "com.google.android.play:app-update", version.ref = "appUpdate" } avif-coder = { module = "com.github.awxkee:avif-coder", version.ref = "avifCoder" } avif-coder-coil = { module = "com.github.awxkee:avif-coder-coil", version.ref = "avifCoderCoil" } -compose = { module = "com.github.zed-alpha.shadow-gadgets:compose", version.ref = "shadowGadgets" } +shadowGadgets = { module = "com.github.zed-alpha.shadow-gadgets:compose", version.ref = "shadowGadgets" } datastore-preferences-android = { module = "androidx.datastore:datastore-preferences-android", version.ref = "androidx-datastorePreferencesAndroid" } fadingEdges = { module = "com.github.t8rin:ComposeFadingEdges", version.ref = "fadingEdges" } firebase-crashlytics-ktx = { module = "com.google.firebase:firebase-crashlytics-ktx", version.ref = "firebaseCrashlyticsKtx" } @@ -144,10 +145,14 @@ decomposeExtensions = { module = "com.arkivanov.decompose:extensions-compose", v shadowsPlus = { module = "com.github.GIGAMOLE:ComposeShadowsPlus", version.ref = "shadowsPlus" } dagger-hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hilt" } desugaring = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugaring" } -coilCompose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } -coilGif = { module = "io.coil-kt:coil-gif", version.ref = "coil" } -coilSvg = { module = "io.coil-kt:coil-svg", version.ref = "coil" } -coil = { module = "io.coil-kt:coil", version.ref = "coil" } + +ktor = { module = "io.ktor:ktor-client-android", version.ref = "ktor" } +coilNetwork = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil" } +coilCompose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil" } +coilGif = { module = "io.coil-kt.coil3:coil-gif", version.ref = "coil" } +coilSvg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" } +coil = { module = "io.coil-kt.coil3:coil", version.ref = "coil" } + firebase-analytics-ktx = { module = "com.google.firebase:firebase-analytics-ktx", version.ref = "firebaseAnalyticsKtx" } jxl-coder-coil = { module = "io.github.awxkee:jxl-coder-coil", version.ref = "jxlCoderCoil" } jxl-coder = { module = "io.github.awxkee:jxl-coder", version.ref = "jxlCoder" } @@ -183,6 +188,7 @@ detekt-gradle = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", v detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" } detekt-compose = { module = "io.nlopez.compose.rules:detekt", version.ref = "detektCompose" } aboutlibraries-gradle = { module = "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin", version.ref = "aboutlibraries" } +compose-compiler-gradle = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" } [plugins] image-toolbox-library = { id = "image.toolbox.library", version = "unspecified" }