diff --git a/android/build.gradle.kts b/android/build.gradle.kts index e491a126..e933a2fe 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -28,7 +28,8 @@ dependencies { implementation(libs.accompanist.pagerIndicators) implementation(libs.accompanist.flowLayout) implementation(libs.accompanist.systemUIController) - implementation(libs.imageloader) + implementation(libs.imageloader.core) + implementation(libs.imageloader.moko) implementation(libs.materialDialogs.core) // Android diff --git a/build.gradle.kts b/build.gradle.kts index 27575add..4d154ecc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,7 +22,7 @@ plugins { alias(libs.plugins.ktorfit) apply false alias(libs.plugins.aboutLibraries) apply false alias(libs.plugins.versions) - id("com.louiscad.complete-kotlin") version "1.1.0" + //id("com.louiscad.complete-kotlin") version "1.1.0" } allprojects { diff --git a/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/Dispatchers.kt b/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/Dispatchers.kt index c6aba9d9..1aed5fe1 100644 --- a/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/Dispatchers.kt +++ b/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/Dispatchers.kt @@ -8,6 +8,7 @@ package ca.gosyer.jui.core.lang import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -expect val Dispatchers.IO: CoroutineDispatcher +val Dispatchers.IO: CoroutineDispatcher + get() = IO diff --git a/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/PriorityChannel.kt b/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/PriorityChannel.kt index 4a629881..488a1162 100644 --- a/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/PriorityChannel.kt +++ b/core/src/commonMain/kotlin/ca/gosyer/jui/core/lang/PriorityChannel.kt @@ -6,7 +6,7 @@ package ca.gosyer.jui.core.lang -import com.soywiz.kds.PriorityQueue +import korlibs.datastructure.PriorityQueue import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi diff --git a/core/src/iosMain/kotlin/ca/gosyer/jui/core/lang/IosDispatchers.kt b/core/src/iosMain/kotlin/ca/gosyer/jui/core/lang/IosDispatchers.kt deleted file mode 100644 index 94e430a9..00000000 --- a/core/src/iosMain/kotlin/ca/gosyer/jui/core/lang/IosDispatchers.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package ca.gosyer.jui.core.lang - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi - -@OptIn(ExperimentalCoroutinesApi::class) -private val ioDispatcher = Dispatchers.Default.limitedParallelism(64) - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -actual val Dispatchers.IO: CoroutineDispatcher - get() = ioDispatcher diff --git a/core/src/jvmMain/kotlin/ca/gosyer/jui/core/lang/JvmDispatchers.kt b/core/src/jvmMain/kotlin/ca/gosyer/jui/core/lang/JvmDispatchers.kt deleted file mode 100644 index 95c071a4..00000000 --- a/core/src/jvmMain/kotlin/ca/gosyer/jui/core/lang/JvmDispatchers.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package ca.gosyer.jui.core.lang - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers - -@Suppress("EXTENSION_SHADOWED_BY_MEMBER") -actual val Dispatchers.IO: CoroutineDispatcher - get() = IO diff --git a/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt b/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt index 26d62562..573e973e 100644 --- a/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt +++ b/data/src/commonMain/kotlin/ca/gosyer/jui/data/DataComponent.kt @@ -26,10 +26,10 @@ import me.tatarka.inject.annotations.Provides interface DataComponent { @Provides - fun ktorfit(http: Http, serverPreferences: ServerPreferences, flowIOResponseConverter: FlowIOResponseConverter) = Ktorfit + fun ktorfit(http: Http, serverPreferences: ServerPreferences) = Ktorfit .Builder() .httpClient(http) - .responseConverter(flowIOResponseConverter) + .converterFactories(FlowConverterFactory()) .baseUrl(serverPreferences.serverUrl().get().toString().addSuffix('/')) .build() diff --git a/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowConverterFactory.kt b/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowConverterFactory.kt new file mode 100644 index 00000000..3031eca3 --- /dev/null +++ b/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowConverterFactory.kt @@ -0,0 +1,58 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package ca.gosyer.jui.data + +import ca.gosyer.jui.core.lang.IO +import de.jensklingenberg.ktorfit.Ktorfit +import de.jensklingenberg.ktorfit.converter.Converter +import de.jensklingenberg.ktorfit.internal.TypeData +import io.ktor.client.call.body +import io.ktor.client.statement.HttpResponse +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.flowOn + +class FlowConverterFactory : Converter.Factory { + + private class FlowResponseConverter( + val typeData: TypeData, + val ktorfit: Ktorfit + ) : Converter.ResponseConverter> { + + override fun convert(getResponse: suspend () -> HttpResponse): Flow { + return flow { + val response = getResponse() + + val convertedBody = ktorfit.nextSuspendResponseConverter( + null, + typeData.typeArgs.first() + )?.convert(response) + ?: response.body(typeData.typeArgs.first().typeInfo) + emit(convertedBody) + }.flowOn(Dispatchers.IO) + } + } + + override fun responseConverter( + typeData: TypeData, + ktorfit: Ktorfit + ): Converter.ResponseConverter? { + if (typeData.typeInfo.type == Flow::class) { + return FlowResponseConverter(typeData, ktorfit) + } + return null + } + + override fun suspendResponseConverter( + typeData: TypeData, + ktorfit: Ktorfit + ): Converter.SuspendResponseConverter? { + return null + } +} + diff --git a/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt b/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt deleted file mode 100644 index b524cffc..00000000 --- a/data/src/commonMain/kotlin/ca/gosyer/jui/data/FlowIOResponseConverter.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package ca.gosyer.jui.data - -import ca.gosyer.jui.core.lang.IO -import de.jensklingenberg.ktorfit.Ktorfit -import de.jensklingenberg.ktorfit.converter.request.ResponseConverter -import de.jensklingenberg.ktorfit.internal.TypeData -import io.ktor.client.statement.HttpResponse -import io.ktor.util.reflect.TypeInfo -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.flowOn -import kotlinx.serialization.json.Json -import me.tatarka.inject.annotations.Inject - -class FlowIOResponseConverter @Inject constructor(private val json: Json) : ResponseConverter { - - override fun supportedType(typeData: TypeData, isSuspend: Boolean): Boolean { - return typeData.qualifiedName == "kotlinx.coroutines.flow.Flow" - } - - override fun wrapResponse( - typeData: TypeData, - requestFunction: suspend () -> Pair, - ktorfit: Ktorfit, - ): Any { - return flow { - try { - val (info, response) = requestFunction() - if (info.type == HttpResponse::class) { - emit(response!!) - } else { - emit(decodeType(response!!, info, json)) - } - } catch (exception: Exception) { - throw exception - } - }.flowOn(Dispatchers.IO) - } -} - -expect suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any diff --git a/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt b/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt deleted file mode 100644 index 83922b8d..00000000 --- a/data/src/iosMain/kotlin/ca/gosyer/jui/data/IosFlowIOResponseConverter.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package ca.gosyer.jui.data - -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.bodyAsText -import io.ktor.util.reflect.TypeInfo -import kotlinx.serialization.json.Json -import kotlinx.serialization.serializer - -actual suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any { - return json.decodeFromString(serializer(typeInfo.kotlinType!!), response.bodyAsText())!! -} diff --git a/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt b/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt deleted file mode 100644 index b182d8d0..00000000 --- a/data/src/jvmMain/kotlin/ca/gosyer/jui/data/JvmFlowIOResponseConverter.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package ca.gosyer.jui.data - -import io.ktor.client.call.body -import io.ktor.client.statement.HttpResponse -import io.ktor.util.reflect.TypeInfo -import kotlinx.serialization.json.Json - -actual suspend fun decodeType(response: HttpResponse, typeInfo: TypeInfo, json: Json): Any { - return response.body(typeInfo) -} diff --git a/desktop/build.gradle.kts b/desktop/build.gradle.kts index c4b46737..049b02e3 100644 --- a/desktop/build.gradle.kts +++ b/desktop/build.gradle.kts @@ -35,7 +35,8 @@ dependencies { implementation(libs.accompanist.pager) implementation(libs.accompanist.pagerIndicators) implementation(libs.accompanist.flowLayout) - implementation(libs.imageloader) + implementation(libs.imageloader.core) + implementation(libs.imageloader.moko) implementation(libs.materialDialogs.core) // UI (Swing) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0029f918..5af718d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,14 +1,14 @@ [versions] # Kotlin -kotlin = "1.8.20" -coroutines = "1.7.0" +kotlin = "1.8.22" +coroutines = "1.7.2" # Serialization -json = "1.5.0" +json = "1.5.1" # Compose -composeGradle = "1.4.0" -composeCompiler = "1.4.5" +composeGradle = "1.4.1" +composeCompiler = "1.4.8" composeAndroidRuntime = "1.4.3" composeAndroidFoundation = "1.4.3" composeAndroidUI = "1.4.3" @@ -19,14 +19,14 @@ composeAndroidMaterial = "1.4.3" voyager = "1.0.0-rc06" accompanist = "0.30.1" googleAccompanist = "0.30.1" -imageloader = "1.4.0" +imageloader = "1.5.3" materialDialogs = "0.9.3" # Android -androidGradle = "8.0.1" +androidGradle = "8.0.2" core = "1.9.0" appCompat = "1.7.0-alpha02" -activityCompose = "1.7.1" +activityCompose = "1.7.2" work = "2.8.1" # Android Lifecycle @@ -36,14 +36,14 @@ lifecycle = "2.6.1" darklaf = "3.0.2" # Ksp -ksp = "1.8.20-1.0.11" +ksp = "1.8.22-1.0.11" # Dependency Injection kotlinInject = "0.6.1" # Network -ktor = "2.3.0" -ktorfit = "1.2.0" +ktor = "2.3.2" +ktorfit = "1.4.2" ktorfitCompiler = "1.0.0" # Logging @@ -60,23 +60,23 @@ multiplatformSettings = "1.0.0-alpha01" # Utility desugarJdkLibs = "2.0.3" -aboutLibraries = "10.6.3" +aboutLibraries = "10.8.0" dateTime = "0.4.0" immutableCollections = "0.3.5" -kds = "3.4.0" +kds = "4.0.7" # Localization -moko = "0.22.0" +moko = "0.23.0" # BuildConfigs -buildconfig = "4.0.4" +buildconfig = "4.1.1" buildkonfig = "0.13.3" # Linter -kotlinter = "3.14.0" +kotlinter = "3.15.0" # Version updates -versions = "0.46.0" +versions = "0.47.0" # Optimizer proguard = "7.2.2" @@ -111,7 +111,8 @@ accompanist-pager = { module = "ca.gosyer:accompanist-pager", version.ref = "acc accompanist-pagerIndicators = { module = "ca.gosyer:accompanist-pager-indicators", version.ref = "accompanist" } accompanist-flowLayout = { module = "ca.gosyer:accompanist-flowlayout", version.ref = "accompanist" } accompanist-systemUIController = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "googleAccompanist" } -imageloader = { module = "io.github.qdsfdhvh:image-loader", version.ref = "imageloader" } +imageloader-core = { module = "io.github.qdsfdhvh:image-loader", version.ref = "imageloader" } +imageloader-moko = { module = "io.github.qdsfdhvh:image-loader-extension-moko-resources", version.ref = "imageloader" } materialDialogs-core = { module = "ca.gosyer:compose-material-dialogs-core", version.ref = "materialDialogs" } # Android diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index ccebba77..c1962a79 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d3..a3638774 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 79a61d42..aeb74cbb 100755 --- a/gradlew +++ b/gradlew @@ -85,9 +85,6 @@ done APP_BASE_NAME=${0##*/} APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -197,6 +194,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/ios/build.gradle.kts b/ios/build.gradle.kts index ce67f686..5611ca1a 100644 --- a/ios/build.gradle.kts +++ b/ios/build.gradle.kts @@ -60,7 +60,8 @@ kotlin { implementation(libs.accompanist.pager) implementation(libs.accompanist.pagerIndicators) implementation(libs.accompanist.flowLayout) - implementation(libs.imageloader) + implementation(libs.imageloader.core) + implementation(libs.imageloader.moko) implementation(libs.materialDialogs.core) // Threading diff --git a/presentation/build.gradle.kts b/presentation/build.gradle.kts index 6f63aab1..a285f827 100644 --- a/presentation/build.gradle.kts +++ b/presentation/build.gradle.kts @@ -34,7 +34,6 @@ kotlin { languageSettings { optIn("kotlin.RequiresOptIn") optIn("kotlinx.coroutines.ExperimentalCoroutinesApi") - optIn("com.google.accompanist.pager.ExperimentalPagerApi") optIn("androidx.compose.animation.ExperimentalAnimationApi") optIn("androidx.compose.foundation.ExperimentalFoundationApi") optIn("androidx.compose.material.ExperimentalMaterialApi") @@ -45,7 +44,8 @@ kotlin { dependencies { api(kotlin("stdlib-common")) api(libs.coroutines.core) - api(libs.imageloader) + api(libs.imageloader.core) + api(libs.imageloader.moko) api(libs.voyager.core) api(libs.voyager.navigation) api(libs.voyager.transitions) diff --git a/presentation/src/androidMain/kotlin/ca/gosyer/jui/ui/base/image/AndroidImageLoaderBuilder.kt b/presentation/src/androidMain/kotlin/ca/gosyer/jui/ui/base/image/AndroidImageLoaderBuilder.kt index f4ebb963..48ea1190 100644 --- a/presentation/src/androidMain/kotlin/ca/gosyer/jui/ui/base/image/AndroidImageLoaderBuilder.kt +++ b/presentation/src/androidMain/kotlin/ca/gosyer/jui/ui/base/image/AndroidImageLoaderBuilder.kt @@ -14,12 +14,17 @@ import com.seiko.imageloader.cache.memory.MemoryCacheBuilder import com.seiko.imageloader.component.ComponentRegistryBuilder import com.seiko.imageloader.component.setupDefaultComponents import com.seiko.imageloader.option.Options +import com.seiko.imageloader.option.OptionsBuilder +import com.seiko.imageloader.option.androidContext import okio.Path.Companion.toOkioPath -actual val imageConfig: Options.ImageConfig = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - Options.ImageConfig.ARGB_8888 -} else { - Options.ImageConfig.HARDWARE +actual fun OptionsBuilder.configure(contextWrapper: ContextWrapper) { + imageConfig = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { + Options.ImageConfig.ARGB_8888 + } else { + Options.ImageConfig.HARDWARE + } + androidContext(contextWrapper) } actual fun ComponentRegistryBuilder.register(contextWrapper: ContextWrapper, http: Http) { diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/UiComponent.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/UiComponent.kt index 7802c3eb..e9027bfe 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/UiComponent.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/UiComponent.kt @@ -9,6 +9,7 @@ package ca.gosyer.jui.ui.base import androidx.compose.runtime.ProvidedValue import androidx.compose.runtime.compositionLocalOf import ca.gosyer.jui.core.di.AppScope +import ca.gosyer.jui.core.io.SYSTEM import ca.gosyer.jui.ui.ViewModelComponent import ca.gosyer.jui.ui.base.image.ImageLoaderProvider import ca.gosyer.jui.ui.base.image.configure @@ -17,6 +18,7 @@ import com.seiko.imageloader.ImageLoader import com.seiko.imageloader.LocalImageLoader import com.seiko.imageloader.cache.disk.DiskCache import me.tatarka.inject.annotations.Provides +import okio.FileSystem typealias ImageCache = DiskCache @@ -35,15 +37,22 @@ interface UiComponent { @AppScope @Provides - fun imageLoaderFactory(imageLoaderProvider: ImageLoaderProvider, imageCache: ImageCache): ImageLoader = imageLoaderProvider.get(imageCache) + fun imageLoaderFactory( + imageLoaderProvider: ImageLoaderProvider, + imageCache: ImageCache + ): ImageLoader = imageLoaderProvider.get(imageCache) @AppScope @Provides - fun imageCacheFactory(): ImageCache = DiskCache { configure(contextWrapper, "image_cache") } + fun imageCacheFactory(): ImageCache = DiskCache(FileSystem.SYSTEM) { + configure(contextWrapper, "image_cache") + } @AppScope @Provides - fun chapterCacheFactory(): ChapterCache = DiskCache { configure(contextWrapper, "chapter_cache") } + fun chapterCacheFactory(): ChapterCache = DiskCache(FileSystem.SYSTEM) { + configure(contextWrapper, "chapter_cache") + } @Provides fun getHooks(viewModelComponent: ViewModelComponent) = arrayOf( diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/image/ImageLoaderProvider.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/image/ImageLoaderProvider.kt index 590e7a7c..88a25948 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/image/ImageLoaderProvider.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/base/image/ImageLoaderProvider.kt @@ -17,9 +17,11 @@ import com.seiko.imageloader.ImageLoader import com.seiko.imageloader.cache.disk.DiskCacheBuilder import com.seiko.imageloader.cache.memory.MemoryCacheBuilder import com.seiko.imageloader.component.ComponentRegistryBuilder +import com.seiko.imageloader.component.fetcher.MokoResourceFetcher import com.seiko.imageloader.component.keyer.Keyer import com.seiko.imageloader.component.mapper.Mapper import com.seiko.imageloader.option.Options +import com.seiko.imageloader.option.OptionsBuilder import io.ktor.http.Url import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope @@ -37,6 +39,7 @@ class ImageLoaderProvider @Inject constructor( return ImageLoader { components { register(context, http) + add(MokoResourceFetcher.Factory()) add(MangaCoverMapper()) add(MangaCoverKeyer()) add(ExtensionIconMapper()) @@ -44,7 +47,9 @@ class ImageLoaderProvider @Inject constructor( add(SourceIconMapper()) add(SourceIconKeyer()) } - options.config = imageConfig + options { + configure(context) + } interceptor { diskCache { imageCache } memoryCacheConfig { configure(context) } @@ -61,7 +66,7 @@ class ImageLoaderProvider @Inject constructor( } class MangaCoverKeyer : Keyer { - override fun key(data: Any, options: Options): String? { + override fun key(data: Any, options: Options, type: Keyer.Type): String? { if (data !is Manga) return null return "${data.sourceId}-${data.thumbnailUrl}-${data.thumbnailUrlLastFetched}" } @@ -76,7 +81,7 @@ class ImageLoaderProvider @Inject constructor( } class ExtensionIconKeyer : Keyer { - override fun key(data: Any, options: Options): String? { + override fun key(data: Any, options: Options, type: Keyer.Type): String? { if (data !is Extension) return null return data.iconUrl } @@ -91,14 +96,14 @@ class ImageLoaderProvider @Inject constructor( } class SourceIconKeyer : Keyer { - override fun key(data: Any, options: Options): String? { + override fun key(data: Any, options: Options, type: Keyer.Type): String? { if (data !is Source) return null return data.iconUrl } } } -expect val imageConfig: Options.ImageConfig +expect fun OptionsBuilder.configure(contextWrapper: ContextWrapper) expect fun ComponentRegistryBuilder.register(contextWrapper: ContextWrapper, http: Http) diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt index 457dc67d..7a49ab8c 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryPager.kt @@ -7,6 +7,8 @@ package ca.gosyer.jui.ui.library.components import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PagerState import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState @@ -16,8 +18,6 @@ import ca.gosyer.jui.domain.library.model.DisplayMode import ca.gosyer.jui.ui.library.CategoryState import ca.gosyer.jui.uicore.components.ErrorScreen import ca.gosyer.jui.uicore.components.LoadingScreen -import com.google.accompanist.pager.HorizontalPager -import com.google.accompanist.pager.PagerState import kotlinx.collections.immutable.ImmutableList @Composable diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryScreenContent.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryScreenContent.kt index f0fab261..2cc46f60 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryScreenContent.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryScreenContent.kt @@ -23,6 +23,8 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.foundation.pager.PagerState +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Scaffold @@ -53,8 +55,6 @@ import ca.gosyer.jui.uicore.components.LoadingScreen import ca.gosyer.jui.uicore.insets.navigationBars import ca.gosyer.jui.uicore.insets.statusBars import ca.gosyer.jui.uicore.resources.stringResource -import com.google.accompanist.pager.PagerState -import com.google.accompanist.pager.rememberPagerState import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryTabs.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryTabs.kt index 934981f3..1e5abea8 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryTabs.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/components/LibraryTabs.kt @@ -4,6 +4,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +@file:Suppress("DEPRECATION") + package ca.gosyer.jui.ui.library.components import androidx.compose.animation.AnimatedVisibility @@ -11,6 +13,7 @@ import androidx.compose.animation.expandVertically import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Divider import androidx.compose.material.MaterialTheme @@ -24,10 +27,11 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEachIndexed import ca.gosyer.jui.domain.category.model.Category -import com.google.accompanist.pager.PagerState +import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.pagerTabIndicatorOffset import kotlinx.collections.immutable.ImmutableList +@OptIn(ExperimentalPagerApi::class) @Composable fun LibraryTabs( visible: Boolean, diff --git a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/settings/LibrarySheet.kt b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/settings/LibrarySheet.kt index 5a581e0e..0fcd7623 100644 --- a/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/settings/LibrarySheet.kt +++ b/presentation/src/commonMain/kotlin/ca/gosyer/jui/ui/library/settings/LibrarySheet.kt @@ -4,6 +4,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +@file:Suppress("DEPRECATION") + package ca.gosyer.jui.ui.library.settings import androidx.compose.foundation.layout.Box @@ -11,6 +13,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.Tab @@ -27,9 +31,8 @@ import ca.gosyer.jui.uicore.components.VerticalScrollbar import ca.gosyer.jui.uicore.components.rememberScrollbarAdapter import ca.gosyer.jui.uicore.components.scrollbarPadding import ca.gosyer.jui.uicore.resources.stringResource -import com.google.accompanist.pager.HorizontalPager +import com.google.accompanist.pager.ExperimentalPagerApi import com.google.accompanist.pager.pagerTabIndicatorOffset -import com.google.accompanist.pager.rememberPagerState import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.launch @@ -39,6 +42,7 @@ enum class LibrarySheetTabs(val res: StringResource) { DISPLAY(MR.strings.library_display), } +@OptIn(ExperimentalPagerApi::class) @Composable fun LibrarySheet( libraryFilters: @Composable () -> Unit, @@ -68,7 +72,7 @@ fun LibrarySheet( } } HorizontalPager( - count = LibrarySheetTabs.values().size, + pageCount = LibrarySheetTabs.values().size, state = pagerState, verticalAlignment = Alignment.Top, ) { diff --git a/presentation/src/desktopMain/kotlin/ca/gosyer/jui/ui/base/image/DesktopImageLoaderBuilder.kt b/presentation/src/desktopMain/kotlin/ca/gosyer/jui/ui/base/image/DesktopImageLoaderBuilder.kt index 43832625..ec307e59 100644 --- a/presentation/src/desktopMain/kotlin/ca/gosyer/jui/ui/base/image/DesktopImageLoaderBuilder.kt +++ b/presentation/src/desktopMain/kotlin/ca/gosyer/jui/ui/base/image/DesktopImageLoaderBuilder.kt @@ -13,9 +13,10 @@ import com.seiko.imageloader.cache.disk.DiskCacheBuilder import com.seiko.imageloader.cache.memory.MemoryCacheBuilder import com.seiko.imageloader.component.ComponentRegistryBuilder import com.seiko.imageloader.component.setupDefaultComponents -import com.seiko.imageloader.option.Options +import com.seiko.imageloader.option.OptionsBuilder -actual val imageConfig: Options.ImageConfig = Options.ImageConfig.ARGB_8888 +actual fun OptionsBuilder.configure(contextWrapper: ContextWrapper) { +} actual fun ComponentRegistryBuilder.register(contextWrapper: ContextWrapper, http: Http) { setupDefaultComponents(httpClient = { http }) diff --git a/presentation/src/iosMain/kotlin/ca/gosyer/jui/ui/base/image/IosImageLoaderBuilder.kt b/presentation/src/iosMain/kotlin/ca/gosyer/jui/ui/base/image/IosImageLoaderBuilder.kt index ed5a3148..118d9d2f 100644 --- a/presentation/src/iosMain/kotlin/ca/gosyer/jui/ui/base/image/IosImageLoaderBuilder.kt +++ b/presentation/src/iosMain/kotlin/ca/gosyer/jui/ui/base/image/IosImageLoaderBuilder.kt @@ -13,13 +13,14 @@ import com.seiko.imageloader.cache.memory.MemoryCacheBuilder import com.seiko.imageloader.cache.memory.maxSizePercent import com.seiko.imageloader.component.ComponentRegistryBuilder import com.seiko.imageloader.component.setupDefaultComponents -import com.seiko.imageloader.option.Options +import com.seiko.imageloader.option.OptionsBuilder import okio.Path.Companion.toPath import platform.Foundation.NSCachesDirectory import platform.Foundation.NSFileManager import platform.Foundation.NSUserDomainMask -actual val imageConfig: Options.ImageConfig = Options.ImageConfig.ARGB_8888 +actual fun OptionsBuilder.configure(contextWrapper: ContextWrapper) { +} actual fun ComponentRegistryBuilder.register(contextWrapper: ContextWrapper, http: Http) { setupDefaultComponents(httpClient = { http }) diff --git a/ui-core/build.gradle.kts b/ui-core/build.gradle.kts index 757fd32d..6b7e6286 100644 --- a/ui-core/build.gradle.kts +++ b/ui-core/build.gradle.kts @@ -41,7 +41,8 @@ kotlin { dependencies { api(kotlin("stdlib-common")) api(libs.coroutines.core) - api(libs.imageloader) + api(libs.imageloader.core) + api(libs.imageloader.moko) api(libs.voyager.core) api(libs.dateTime) api(libs.immutableCollections)