From 9ca4d689c752e9edd7dd4c8c335fe29a8b1363be Mon Sep 17 00:00:00 2001 From: Vasyl Pidlisniak Date: Wed, 6 Nov 2024 13:45:06 +0100 Subject: [PATCH 1/4] make resources android preview friendly --- .../androidMain/kotlin/ApplicationHolder.kt | 63 +++++++++---------- resources/src/androidMain/kotlin/Resources.kt | 11 ++-- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/base/src/androidMain/kotlin/ApplicationHolder.kt b/base/src/androidMain/kotlin/ApplicationHolder.kt index a48dc0def..11143f4de 100644 --- a/base/src/androidMain/kotlin/ApplicationHolder.kt +++ b/base/src/androidMain/kotlin/ApplicationHolder.kt @@ -20,42 +20,37 @@ package com.splendo.kaluga.base import android.app.Application import android.content.Context -import com.splendo.kaluga.base.ApplicationHolder.Companion.application /** - * Class holding reference to the [Application] running Kaluga - * set [application] to your Application so default constructors work with the proper [Context] + * Class holding reference to the [Application] [Context] running Kaluga + * set [applicationContext] to your Application so default constructors work with the proper [Context] */ -class ApplicationHolder { - companion object { - - /** - * The [Application] running Kaluga - */ - var application: Application? = null - set(application) { - check(field == null) { "Application object can only be set once." } - field = application +object ApplicationHolder { + + private var _applicationContext: Context? = null + set(value) { + check(field == null) { "Application object can only be set once." } + field = value + } + + /** + * Indicates whether [Application] [Context] was set + */ + val isInitialized: Boolean get() = _applicationContext != null + + /** + * The [Context] of the [Application] running Kaluga + */ + var applicationContext: Context + get() { + val context = _applicationContext + checkNotNull(context) { + "You've used ApplicationHolder.applicationContext without setting it on this holder " + + "(you should do this from Application.onCreate() or in your test)" } - - /** - * The [Context] of the [application] - */ - val applicationContext: Context - get() { - val application = this.application - checkNotNull(application) { - "You've used ApplicationHolder.applicationContext without setting the Application on this holder " + - "(you should do this from Application.onCreate() or in your test)" - } - - val context = application.applicationContext - checkNotNull(context) { - "ApplicationContext is null, this should not happen during runtime if you set a real Application instance on this holder." + - "For testing make sure you set an Application with a real or mock ApplicationContext available." - } - - return context - } - } + return context + } + set(value) { + _applicationContext = value.applicationContext + } } diff --git a/resources/src/androidMain/kotlin/Resources.kt b/resources/src/androidMain/kotlin/Resources.kt index 8b471df78..9590433fa 100644 --- a/resources/src/androidMain/kotlin/Resources.kt +++ b/resources/src/androidMain/kotlin/Resources.kt @@ -24,8 +24,7 @@ import android.graphics.Typeface import android.os.Handler import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat -import com.splendo.kaluga.base.ApplicationHolder.Companion.application -import com.splendo.kaluga.base.ApplicationHolder.Companion.applicationContext +import com.splendo.kaluga.base.ApplicationHolder import kotlinx.coroutines.CompletableDeferred /** @@ -33,7 +32,7 @@ import kotlinx.coroutines.CompletableDeferred * @param context the [Context] from which to load the string resources */ actual class DefaultStringLoader(private val context: Context?) : StringLoader { - actual constructor() : this(if (application != null) applicationContext else null) + actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) actual override fun loadString(identifier: String, defaultValue: String): String { if (context == null) { return defaultValue @@ -63,7 +62,7 @@ actual class DefaultStringLoader(private val context: Context?) : StringLoader { * @param context the [Context] from which to load the color resources */ actual class DefaultColorLoader(private val context: Context?) : KalugaColorLoader { - actual constructor() : this(if (application != null) applicationContext else null) + actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) actual override fun loadColor(identifier: String, defaultValue: KalugaColor?): KalugaColor? { if (context == null) { return defaultValue @@ -93,7 +92,7 @@ actual class DefaultColorLoader(private val context: Context?) : KalugaColorLoad * @param context the [Context] from which to load the image resources */ actual class DefaultImageLoader(private val context: Context?) : ImageLoader { - actual constructor() : this(if (application != null) applicationContext else null) + actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) actual override fun loadImage(identifier: String, defaultValue: KalugaImage?): KalugaImage? { if (context == null) { return defaultValue @@ -113,7 +112,7 @@ actual class DefaultImageLoader(private val context: Context?) : ImageLoader { * @param handler a [Handler] for the thread the completion of loading the font should called on. If `null`, the UI thread will be used. */ actual class DefaultFontLoader(private val context: Context?, private val handler: Handler?) : FontLoader { - actual constructor() : this(if (application != null) applicationContext else null, null) + actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null, null) actual override suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? { if (context == null) { return defaultValue From 4190afa6d2e34a75a39b7f41d969e406394bdd38 Mon Sep 17 00:00:00 2001 From: Vasyl Pidlisniak Date: Wed, 6 Nov 2024 15:12:03 +0100 Subject: [PATCH 2/4] cleanup + api dump --- base/api/android/base.api | 10 +- resources-compose/api/resources-compose.api | 4 + .../src/main/kotlin/KalugaPreview.kt | 58 ++++++++++ resources/api/resources.api | 6 +- resources/src/androidMain/kotlin/Resources.kt | 107 ++++++------------ resources/src/commonMain/kotlin/Resources.kt | 4 +- resources/src/iosMain/kotlin/Resources.kt | 2 +- .../api/test-utils-resources.api | 4 +- .../src/commonMain/kotlin/MockResources.kt | 2 +- 9 files changed, 110 insertions(+), 87 deletions(-) create mode 100644 resources-compose/src/main/kotlin/KalugaPreview.kt diff --git a/base/api/android/base.api b/base/api/android/base.api index 78030068f..0db0ed771 100644 --- a/base/api/android/base.api +++ b/base/api/android/base.api @@ -1,12 +1,8 @@ public final class com/splendo/kaluga/base/ApplicationHolder { - public static final field Companion Lcom/splendo/kaluga/base/ApplicationHolder$Companion; - public fun ()V -} - -public final class com/splendo/kaluga/base/ApplicationHolder$Companion { - public final fun getApplication ()Landroid/app/Application; + public static final field INSTANCE Lcom/splendo/kaluga/base/ApplicationHolder; public final fun getApplicationContext ()Landroid/content/Context; - public final fun setApplication (Landroid/app/Application;)V + public final fun isInitialized ()Z + public final fun setApplicationContext (Landroid/content/Context;)V } public final class com/splendo/kaluga/base/KalugaThread { diff --git a/resources-compose/api/resources-compose.api b/resources-compose/api/resources-compose.api index 255a90f51..e3d9abd7a 100644 --- a/resources-compose/api/resources-compose.api +++ b/resources-compose/api/resources-compose.api @@ -29,6 +29,10 @@ public final class com/splendo/kaluga/resources/compose/KalugaLabelKt { public static final fun PreviewKalugaLabel (Landroidx/compose/runtime/Composer;I)V } +public final class com/splendo/kaluga/resources/compose/KalugaPreviewKt { + public static final fun KalugaPreview (Ljava/lang/String;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V +} + public final class com/splendo/kaluga/resources/compose/TextAlignmentKt { public static final fun getComposable (Lcom/splendo/kaluga/resources/stylable/KalugaTextAlignment;)I } diff --git a/resources-compose/src/main/kotlin/KalugaPreview.kt b/resources-compose/src/main/kotlin/KalugaPreview.kt new file mode 100644 index 000000000..c63567ab8 --- /dev/null +++ b/resources-compose/src/main/kotlin/KalugaPreview.kt @@ -0,0 +1,58 @@ +/* + Copyright 2024 Splendo Consulting B.V. The Netherlands + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ + +package com.splendo.kaluga.resources.compose + +import android.content.Context +import android.content.ContextWrapper +import android.content.res.Configuration +import android.content.res.Resources +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import com.splendo.kaluga.base.ApplicationHolder +import com.splendo.kaluga.resources.FontLoader +import com.splendo.kaluga.resources.KalugaFont + +/** + * Sets up an infrastructure for previews. + * @param resourcePackageOverride if provided, overrides a lookup package for resources + * @param content a preview content + */ +@Composable +fun KalugaPreview(resourcePackageOverride: String? = null, content: @Composable () -> Unit) { + ApplicationHolder.applicationContext = PreviewContextWrapper( + base = LocalContext.current.applicationContext, + packageNameOverride = resourcePackageOverride, + ) + + content() +} + +private class PreviewContextWrapper private constructor( + base: Context, + private val packageNameOverride: String?, + private val resourcesOverride: Resources?, +) : ContextWrapper(base) { + constructor(base: Context, packageNameOverride: String?) : this(base, packageNameOverride, null) + override fun getPackageName(): String = packageNameOverride ?: super.getPackageName() + override fun createConfigurationContext(overrideConfiguration: Configuration): Context { + @Suppress("DEPRECATION") + return super.createConfigurationContext(overrideConfiguration) + ?: PreviewContextWrapper(this, packageNameOverride, Resources(resources.assets, resources.displayMetrics, overrideConfiguration)) + } + override fun getResources(): Resources = resourcesOverride ?: super.getResources() +} diff --git a/resources/api/resources.api b/resources/api/resources.api index 6204cbe7e..8a7a9a573 100644 --- a/resources/api/resources.api +++ b/resources/api/resources.api @@ -392,8 +392,8 @@ public final class com/splendo/kaluga/resources/DefaultColors { public final class com/splendo/kaluga/resources/DefaultFontLoader : com/splendo/kaluga/resources/FontLoader { public fun ()V - public fun (Landroid/content/Context;Landroid/os/Handler;)V - public fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun (Landroid/content/Context;)V + public fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;)Landroid/graphics/Typeface; } public final class com/splendo/kaluga/resources/DefaultImageLoader : com/splendo/kaluga/resources/ImageLoader { @@ -410,7 +410,7 @@ public final class com/splendo/kaluga/resources/DefaultStringLoader : com/splend } public abstract interface class com/splendo/kaluga/resources/FontLoader { - public abstract fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;)Landroid/graphics/Typeface; } public final class com/splendo/kaluga/resources/FontStyle : java/lang/Enum { diff --git a/resources/src/androidMain/kotlin/Resources.kt b/resources/src/androidMain/kotlin/Resources.kt index 9590433fa..e5eca8257 100644 --- a/resources/src/androidMain/kotlin/Resources.kt +++ b/resources/src/androidMain/kotlin/Resources.kt @@ -1,3 +1,4 @@ +@file:JvmName("ResourcesAndroidKt") /* Copyright 2022 Splendo Consulting B.V. The Netherlands @@ -17,15 +18,28 @@ package com.splendo.kaluga.resources +import android.annotation.SuppressLint import android.content.Context import android.content.res.Configuration import android.content.res.Resources -import android.graphics.Typeface -import android.os.Handler import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat import com.splendo.kaluga.base.ApplicationHolder -import kotlinx.coroutines.CompletableDeferred + +@Suppress("EnumEntryName") +private enum class DefType { + string, plurals, color, drawable, font +} + +@SuppressLint("DiscouragedApi") +private fun Context.getResource(name: String, defType: DefType, get: Context.(Int) -> T?): T? = + try { + resources.getIdentifier(name, defType.name, packageName) + .takeIf { it != 0 } + ?.let { id -> get(id) } + } catch (e: Resources.NotFoundException) { + null + } /** * Default implementation of a [StringLoader]. @@ -33,28 +47,13 @@ import kotlinx.coroutines.CompletableDeferred */ actual class DefaultStringLoader(private val context: Context?) : StringLoader { actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) - actual override fun loadString(identifier: String, defaultValue: String): String { - if (context == null) { - return defaultValue - } - val id = context.resources.getIdentifier(identifier, "string", context.packageName) - return try { - context.getString(id) - } catch (e: Resources.NotFoundException) { - defaultValue - } - } - actual override fun loadQuantityString(identifier: String, quantity: Int, defaultValue: String): String { - if (context == null) { - return defaultValue - } - val id = context.resources.getIdentifier(identifier, "plurals", context.packageName) - return try { - context.resources.getQuantityString(id, quantity, quantity) - } catch (e: Resources.NotFoundException) { - defaultValue - } - } + actual override fun loadString(identifier: String, defaultValue: String): String = + context?.getResource(identifier, DefType.string, Context::getString) + ?: defaultValue + + actual override fun loadQuantityString(identifier: String, quantity: Int, defaultValue: String): String = + context?.getResource(identifier, DefType.plurals) { id -> resources.getQuantityString(id, quantity, quantity) } + ?: defaultValue } /** @@ -63,20 +62,13 @@ actual class DefaultStringLoader(private val context: Context?) : StringLoader { */ actual class DefaultColorLoader(private val context: Context?) : KalugaColorLoader { actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) - actual override fun loadColor(identifier: String, defaultValue: KalugaColor?): KalugaColor? { - if (context == null) { - return defaultValue - } - val id = context.resources.getIdentifier(identifier, "color", context.packageName) - return try { + actual override fun loadColor(identifier: String, defaultValue: KalugaColor?): KalugaColor? = + context?.getResource(identifier, DefType.color) { id -> KalugaColor.DarkLightColor( ContextCompat.getColor(context.themedContext(false), id), ContextCompat.getColor(context.themedContext(true), id), ) - } catch (e: Resources.NotFoundException) { - defaultValue - } - } + } ?: defaultValue private fun Context.themedContext(withNightMode: Boolean): Context { val res: Resources = resources @@ -93,46 +85,19 @@ actual class DefaultColorLoader(private val context: Context?) : KalugaColorLoad */ actual class DefaultImageLoader(private val context: Context?) : ImageLoader { actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) - actual override fun loadImage(identifier: String, defaultValue: KalugaImage?): KalugaImage? { - if (context == null) { - return defaultValue - } - val id = context.resources.getIdentifier(identifier, "drawable", context.packageName) - return try { - ContextCompat.getDrawable(context, id)?.let { KalugaImage(it) } - } catch (e: Resources.NotFoundException) { - defaultValue - } - } + actual override fun loadImage(identifier: String, defaultValue: KalugaImage?): KalugaImage? = + context?.getResource(identifier, DefType.drawable) { id -> ContextCompat.getDrawable(this, id) } + ?.let(::KalugaImage) + ?: defaultValue } /** * Default implementation of a [FontLoader]. * @param context the [Context] from which to load the font resources - * @param handler a [Handler] for the thread the completion of loading the font should called on. If `null`, the UI thread will be used. */ -actual class DefaultFontLoader(private val context: Context?, private val handler: Handler?) : FontLoader { - actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null, null) - actual override suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? { - if (context == null) { - return defaultValue - } - val id = context.resources.getIdentifier(identifier, "font", context.packageName) - return try { - val deferredFont = CompletableDeferred() - val callback = object : ResourcesCompat.FontCallback() { - override fun onFontRetrievalFailed(reason: Int) { - deferredFont.complete(defaultValue) - } - - override fun onFontRetrieved(typeface: Typeface) { - deferredFont.complete(typeface) - } - } - ResourcesCompat.getFont(context, id, callback, handler) - deferredFont.await() - } catch (e: Resources.NotFoundException) { - defaultValue - } - } +actual class DefaultFontLoader(private val context: Context?) : FontLoader { + actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) + actual override fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? = + context?.getResource(identifier, DefType.font) { id -> ResourcesCompat.getFont(context, id) } + ?: defaultValue } diff --git a/resources/src/commonMain/kotlin/Resources.kt b/resources/src/commonMain/kotlin/Resources.kt index dc8b4cf8c..ca01c96f4 100644 --- a/resources/src/commonMain/kotlin/Resources.kt +++ b/resources/src/commonMain/kotlin/Resources.kt @@ -98,14 +98,14 @@ interface FontLoader { * @param defaultValue The [KalugaFont] to return if no match was found for the identifier. * @return The associated [KalugaFont] resources or [defaultValue] if no such resource was found. */ - suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? + fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? } /** * Default implementation of a [FontLoader]. */ expect class DefaultFontLoader() : FontLoader { - override suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? + override fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? } /** diff --git a/resources/src/iosMain/kotlin/Resources.kt b/resources/src/iosMain/kotlin/Resources.kt index d35909fa3..23fe8da31 100644 --- a/resources/src/iosMain/kotlin/Resources.kt +++ b/resources/src/iosMain/kotlin/Resources.kt @@ -69,5 +69,5 @@ actual class DefaultImageLoader(private val bundle: NSBundle, private val traitC * Default implementation of a [FontLoader]. */ actual class DefaultFontLoader actual constructor() : FontLoader { - actual override suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? = UIFont.fontWithName(identifier, UIFont.labelFontSize) ?: defaultValue + actual override fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? = UIFont.fontWithName(identifier, UIFont.labelFontSize) ?: defaultValue } diff --git a/test-utils-resources/api/test-utils-resources.api b/test-utils-resources/api/test-utils-resources.api index c09e78bbb..ce50d5e25 100644 --- a/test-utils-resources/api/test-utils-resources.api +++ b/test-utils-resources/api/test-utils-resources.api @@ -10,8 +10,8 @@ public final class com/splendo/kaluga/test/resources/MockFontLoader : com/splend public fun ()V public fun (Z)V public synthetic fun (ZILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun getLoadFontMock ()Lcom/splendo/kaluga/test/base/mock/SuspendMethodMock; - public fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun getLoadFontMock ()Lcom/splendo/kaluga/test/base/mock/MethodMock; + public fun loadFont (Ljava/lang/String;Landroid/graphics/Typeface;)Landroid/graphics/Typeface; } public final class com/splendo/kaluga/test/resources/MockImageLoader : com/splendo/kaluga/resources/ImageLoader { diff --git a/test-utils-resources/src/commonMain/kotlin/MockResources.kt b/test-utils-resources/src/commonMain/kotlin/MockResources.kt index 0ef365817..f3a07b67d 100644 --- a/test-utils-resources/src/commonMain/kotlin/MockResources.kt +++ b/test-utils-resources/src/commonMain/kotlin/MockResources.kt @@ -115,7 +115,7 @@ class MockFontLoader(private val returnMock: Boolean = false) : FontLoader { } } - override suspend fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? = loadFontMock.call(identifier, defaultValue) + override fun loadFont(identifier: String, defaultValue: KalugaFont?): KalugaFont? = loadFontMock.call(identifier, defaultValue) } /** From 9c6604541ee504857fbee347210ee430674e7e98 Mon Sep 17 00:00:00 2001 From: Vasyl Pidlisniak Date: Thu, 14 Nov 2024 12:39:14 +0100 Subject: [PATCH 3/4] fix example app --- .../main/java/com/splendo/kaluga/example/ExampleApplication.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/android/src/main/java/com/splendo/kaluga/example/ExampleApplication.kt b/example/android/src/main/java/com/splendo/kaluga/example/ExampleApplication.kt index 6c048af59..eace3f47f 100644 --- a/example/android/src/main/java/com/splendo/kaluga/example/ExampleApplication.kt +++ b/example/android/src/main/java/com/splendo/kaluga/example/ExampleApplication.kt @@ -34,7 +34,7 @@ class ExampleApplication : Application() { override fun onCreate() { super.onCreate() - ApplicationHolder.application = this + ApplicationHolder.applicationContext = this initKoin( listOf( From 7a746664e1c19d1e54ddc8a68622212f064debe8 Mon Sep 17 00:00:00 2001 From: Vasyl Pidlisniak Date: Thu, 14 Nov 2024 13:10:45 +0100 Subject: [PATCH 4/4] lint --- .../viewmodel/resources/ColorViewModel.kt | 8 ++-- .../src/main/kotlin/KalugaPreview.kt | 9 +---- resources/src/androidMain/kotlin/Resources.kt | 39 ++++++++++--------- 3 files changed, 26 insertions(+), 30 deletions(-) diff --git a/example/shared/src/commonMain/kotlin/com/splendo/kaluga/example/shared/viewmodel/resources/ColorViewModel.kt b/example/shared/src/commonMain/kotlin/com/splendo/kaluga/example/shared/viewmodel/resources/ColorViewModel.kt index d70d43621..67464f0cd 100644 --- a/example/shared/src/commonMain/kotlin/com/splendo/kaluga/example/shared/viewmodel/resources/ColorViewModel.kt +++ b/example/shared/src/commonMain/kotlin/com/splendo/kaluga/example/shared/viewmodel/resources/ColorViewModel.kt @@ -135,8 +135,8 @@ class ColorViewModel(private val alertPresenterBuilder: BaseAlertPresenter.Build is KalugaColor.RGBColor -> color is KalugaColor.DarkLightColor -> color.defaultColor else -> throw IllegalArgumentException("Invalid Color $color") - } - ) + }, + ), ) } @@ -147,8 +147,8 @@ class ColorViewModel(private val alertPresenterBuilder: BaseAlertPresenter.Build is KalugaColor.RGBColor -> color is KalugaColor.DarkLightColor -> color.darkColor else -> throw IllegalArgumentException("Invalid Color $color") - } - ) + }, + ), ) } diff --git a/resources-compose/src/main/kotlin/KalugaPreview.kt b/resources-compose/src/main/kotlin/KalugaPreview.kt index c63567ab8..2322f9c8b 100644 --- a/resources-compose/src/main/kotlin/KalugaPreview.kt +++ b/resources-compose/src/main/kotlin/KalugaPreview.kt @@ -24,8 +24,6 @@ import android.content.res.Resources import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalContext import com.splendo.kaluga.base.ApplicationHolder -import com.splendo.kaluga.resources.FontLoader -import com.splendo.kaluga.resources.KalugaFont /** * Sets up an infrastructure for previews. @@ -42,11 +40,8 @@ fun KalugaPreview(resourcePackageOverride: String? = null, content: @Composable content() } -private class PreviewContextWrapper private constructor( - base: Context, - private val packageNameOverride: String?, - private val resourcesOverride: Resources?, -) : ContextWrapper(base) { +private class PreviewContextWrapper private constructor(base: Context, private val packageNameOverride: String?, private val resourcesOverride: Resources?) : + ContextWrapper(base) { constructor(base: Context, packageNameOverride: String?) : this(base, packageNameOverride, null) override fun getPackageName(): String = packageNameOverride ?: super.getPackageName() override fun createConfigurationContext(overrideConfiguration: Configuration): Context { diff --git a/resources/src/androidMain/kotlin/Resources.kt b/resources/src/androidMain/kotlin/Resources.kt index e5eca8257..9b0fe109b 100644 --- a/resources/src/androidMain/kotlin/Resources.kt +++ b/resources/src/androidMain/kotlin/Resources.kt @@ -28,18 +28,21 @@ import com.splendo.kaluga.base.ApplicationHolder @Suppress("EnumEntryName") private enum class DefType { - string, plurals, color, drawable, font + string, + plurals, + color, + drawable, + font, } @SuppressLint("DiscouragedApi") -private fun Context.getResource(name: String, defType: DefType, get: Context.(Int) -> T?): T? = - try { - resources.getIdentifier(name, defType.name, packageName) - .takeIf { it != 0 } - ?.let { id -> get(id) } - } catch (e: Resources.NotFoundException) { - null - } +private fun Context.getResource(name: String, defType: DefType, get: Context.(Int) -> T?): T? = try { + resources.getIdentifier(name, defType.name, packageName) + .takeIf { it != 0 } + ?.let { id -> get(id) } +} catch (e: Resources.NotFoundException) { + null +} /** * Default implementation of a [StringLoader]. @@ -47,9 +50,8 @@ private fun Context.getResource(name: String, defType: DefType, get: Context */ actual class DefaultStringLoader(private val context: Context?) : StringLoader { actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) - actual override fun loadString(identifier: String, defaultValue: String): String = - context?.getResource(identifier, DefType.string, Context::getString) - ?: defaultValue + actual override fun loadString(identifier: String, defaultValue: String): String = context?.getResource(identifier, DefType.string, Context::getString) + ?: defaultValue actual override fun loadQuantityString(identifier: String, quantity: Int, defaultValue: String): String = context?.getResource(identifier, DefType.plurals) { id -> resources.getQuantityString(id, quantity, quantity) } @@ -62,13 +64,12 @@ actual class DefaultStringLoader(private val context: Context?) : StringLoader { */ actual class DefaultColorLoader(private val context: Context?) : KalugaColorLoader { actual constructor() : this(if (ApplicationHolder.isInitialized) ApplicationHolder.applicationContext else null) - actual override fun loadColor(identifier: String, defaultValue: KalugaColor?): KalugaColor? = - context?.getResource(identifier, DefType.color) { id -> - KalugaColor.DarkLightColor( - ContextCompat.getColor(context.themedContext(false), id), - ContextCompat.getColor(context.themedContext(true), id), - ) - } ?: defaultValue + actual override fun loadColor(identifier: String, defaultValue: KalugaColor?): KalugaColor? = context?.getResource(identifier, DefType.color) { id -> + KalugaColor.DarkLightColor( + ContextCompat.getColor(context.themedContext(false), id), + ContextCompat.getColor(context.themedContext(true), id), + ) + } ?: defaultValue private fun Context.themedContext(withNightMode: Boolean): Context { val res: Resources = resources