diff --git a/components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt b/components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt index b172f792c9..6621a72361 100644 --- a/components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt +++ b/components/resources/library/src/blockingMain/kotlin/org/jetbrains/compose/resources/ResourceState.blocking.kt @@ -5,12 +5,43 @@ import kotlinx.coroutines.runBlocking @Composable internal actual fun rememberResourceState( - key: Any, + key1: Any, getDefault: () -> T, block: suspend (ResourceEnvironment) -> T ): State { val environment = LocalComposeEnvironment.current.rememberEnvironment() - return remember(key, environment) { + return remember(key1, environment) { + mutableStateOf( + runBlocking { block(environment) } + ) + } +} + +@Composable +internal actual fun rememberResourceState( + key1: Any, + key2: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State { + val environment = LocalComposeEnvironment.current.rememberEnvironment() + return remember(key1, key2, environment) { + mutableStateOf( + runBlocking { block(environment) } + ) + } +} + +@Composable +internal actual fun rememberResourceState( + key1: Any, + key2: Any, + key3: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State { + val environment = LocalComposeEnvironment.current.rememberEnvironment() + return remember(key1, key2, key3, environment) { mutableStateOf( runBlocking { block(environment) } ) diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceState.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceState.kt index f09ba40827..e8e38d5e63 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceState.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/ResourceState.kt @@ -10,7 +10,34 @@ import androidx.compose.runtime.State */ @Composable internal expect fun rememberResourceState( - key: Any, + key1: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State + +/** + * This is a platform-specific function that calculates and remembers a state. + * For all platforms except a JS it is a blocking function. + * On the JS platform it loads the state asynchronously and uses `getDefault` as an initial state value. + */ +@Composable +internal expect fun rememberResourceState( + key1: Any, + key2: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State + +/** + * This is a platform-specific function that calculates and remembers a state. + * For all platforms except a JS it is a blocking function. + * On the JS platform it loads the state asynchronously and uses `getDefault` as an initial state value. + */ +@Composable +internal expect fun rememberResourceState( + key1: Any, + key2: Any, + key3: Any, getDefault: () -> T, block: suspend (ResourceEnvironment) -> T ): State \ No newline at end of file diff --git a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt index da3d53eb6c..77913ab495 100644 --- a/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt +++ b/components/resources/library/src/commonMain/kotlin/org/jetbrains/compose/resources/StringResources.kt @@ -123,7 +123,7 @@ private suspend fun loadString( fun stringResource(resource: StringResource, vararg formatArgs: Any): String { val resourceReader = LocalResourceReader.current val args = formatArgs.map { it.toString() } - val str by rememberResourceState(resource, { "" }) { env -> + val str by rememberResourceState(resource, args, { "" }) { env -> loadString(resource, args, resourceReader, env) } return str diff --git a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt b/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt index 3160db93b2..61949ee842 100644 --- a/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt +++ b/components/resources/library/src/commonTest/kotlin/org/jetbrains/compose/resources/ComposeResourceTest.kt @@ -111,6 +111,29 @@ class ComposeResourceTest { assertEquals(listOf("item 1", "item 2", "item 3"), str_arr) } + // https://github.com/JetBrains/compose-multiplatform/issues/4325 + @Test + fun testReadStringFromDifferentArgs() = runComposeUiTest { + var arg by mutableStateOf(42) + var str1 = "" + var str2 = "" + setContent { + CompositionLocalProvider(LocalComposeEnvironment provides TestComposeEnvironment) { + str1 = stringResource(TestStringResource("str_template"), "test1", arg) + str2 = stringResource(TestStringResource("str_template"), "test2", arg) + } + } + + waitForIdle() + assertEquals("Hello, test1! You have 42 new messages.", str1) + assertEquals("Hello, test2! You have 42 new messages.", str2) + + arg = 31415 + waitForIdle() + assertEquals("Hello, test1! You have 31415 new messages.", str1) + assertEquals("Hello, test2! You have 31415 new messages.", str2) + } + @Test fun testLoadStringResource() = runTest { assertEquals("Compose Resources App", getString(TestStringResource("app_name"))) diff --git a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt index 0bd899be07..c254829c81 100644 --- a/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt +++ b/components/resources/library/src/skikoMain/kotlin/org/jetbrains/compose/resources/FontResources.skiko.kt @@ -33,7 +33,7 @@ private val defaultEmptyFont by lazy { Font("org.jetbrains.compose.emptyFont", B @Composable actual fun Font(resource: FontResource, weight: FontWeight, style: FontStyle): Font { val resourceReader = LocalResourceReader.current - val fontFile by rememberResourceState(resource, { defaultEmptyFont }) { env -> + val fontFile by rememberResourceState(resource, weight, style, { defaultEmptyFont }) { env -> val path = resource.getPathByEnvironment(env) val fontBytes = resourceReader.read(path) Font(path, fontBytes, weight, style) diff --git a/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt b/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt index ca6b0fd127..8317c96d2a 100644 --- a/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt +++ b/components/resources/library/src/webMain/kotlin/org/jetbrains/compose/resources/ResourceState.web.kt @@ -8,13 +8,44 @@ import androidx.compose.runtime.remember @Composable internal actual fun rememberResourceState( - key: Any, + key1: Any, getDefault: () -> T, block: suspend (ResourceEnvironment) -> T ): State { val environment = LocalComposeEnvironment.current.rememberEnvironment() - val state = remember(key) { mutableStateOf(getDefault()) } - LaunchedEffect(key) { + val state = remember(key1) { mutableStateOf(getDefault()) } + LaunchedEffect(key1) { + state.value = block(environment) + } + return state +} + +@Composable +internal actual fun rememberResourceState( + key1: Any, + key2: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State { + val environment = LocalComposeEnvironment.current.rememberEnvironment() + val state = remember(key1, key2) { mutableStateOf(getDefault()) } + LaunchedEffect(key1, key2) { + state.value = block(environment) + } + return state +} + +@Composable +internal actual fun rememberResourceState( + key1: Any, + key2: Any, + key3: Any, + getDefault: () -> T, + block: suspend (ResourceEnvironment) -> T +): State { + val environment = LocalComposeEnvironment.current.rememberEnvironment() + val state = remember(key1, key2, key3) { mutableStateOf(getDefault()) } + LaunchedEffect(key1, key2, key3) { state.value = block(environment) } return state