Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get environment and select resource by qualifiers #4018

Merged
merged 12 commits into from
Dec 20, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fun FileRes(paddingValues: PaddingValues) {
) {
Text(
modifier = Modifier.padding(16.dp),
text = "File: 'composeRes/images/droid_icon.xml'",
text = "File: 'composeRes/drawable/droid_icon.xml'",
style = MaterialTheme.typography.titleLarge
)
OutlinedCard(
Expand All @@ -38,7 +38,7 @@ fun FileRes(paddingValues: PaddingValues) {
) {
var bytes by remember { mutableStateOf(ByteArray(0)) }
LaunchedEffect(Unit) {
bytes = readResourceBytes("composeRes/images/droid_icon.xml")
bytes = readResourceBytes("composeRes/drawable/droid_icon.xml")
}
Text(
modifier = Modifier.padding(8.dp).height(200.dp).verticalScroll(rememberScrollState()),
Expand All @@ -54,7 +54,7 @@ fun FileRes(paddingValues: PaddingValues) {
mutableStateOf(ByteArray(0))
}
LaunchedEffect(Unit) {
bytes = readBytes("composeRes/images/droid_icon.xml")
bytes = readResourceBytes("composeRes/drawable/droid_icon.xml")
}
Text(bytes.decodeToString())
""".trimIndent()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fun FontRes(paddingValues: PaddingValues) {
)
}

val fontAwesome = FontFamily(Font(Res.fonts.font_awesome))
val fontAwesome = FontFamily(Font(Res.font.font_awesome))
val symbols = arrayOf(0xf1ba, 0xf238, 0xf21a, 0xf1bb, 0xf1b8, 0xf09b, 0xf269, 0xf1d0, 0xf15a, 0xf293, 0xf1c6)
Text(
modifier = Modifier.padding(16.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Image(
modifier = Modifier.size(100.dp),
painter = painterResource(Res.images.compose),
painter = painterResource(Res.drawable.compose),
contentDescription = null
)
Text(
"""
Image(
painter = painterResource(Res.images.compose)
painter = painterResource(Res.drawable.compose)
)
""".trimIndent()
)
Expand All @@ -47,13 +47,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Image(
modifier = Modifier.size(100.dp),
painter = painterResource(Res.images.insta_icon),
painter = painterResource(Res.drawable.insta_icon),
contentDescription = null
)
Text(
"""
Image(
painter = painterResource(Res.images.insta_icon)
painter = painterResource(Res.drawable.insta_icon)
)
""".trimIndent()
)
Expand All @@ -66,13 +66,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Image(
modifier = Modifier.size(140.dp),
bitmap = imageResource(Res.images.land),
bitmap = imageResource(Res.drawable.land),
contentDescription = null
)
Text(
"""
Image(
bitmap = imageResource(Res.images.land)
bitmap = imageResource(Res.drawable.land)
)
""".trimIndent()
)
Expand All @@ -85,13 +85,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Image(
modifier = Modifier.size(100.dp),
imageVector = vectorResource(Res.images.droid_icon),
imageVector = vectorResource(Res.drawable.droid_icon),
contentDescription = null
)
Text(
"""
Image(
imageVector = vectorResource(Res.images.droid_icon)
imageVector = vectorResource(Res.drawable.droid_icon)
)
""".trimIndent()
)
Expand All @@ -104,13 +104,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Icon(
modifier = Modifier.size(100.dp),
painter = painterResource(Res.images.compose),
painter = painterResource(Res.drawable.compose),
contentDescription = null
)
Text(
"""
Icon(
painter = painterResource(Res.images.compose)
painter = painterResource(Res.drawable.compose)
)
""".trimIndent()
)
Expand All @@ -123,13 +123,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Icon(
modifier = Modifier.size(100.dp),
painter = painterResource(Res.images.insta_icon),
painter = painterResource(Res.drawable.insta_icon),
contentDescription = null
)
Text(
"""
Icon(
painter = painterResource(Res.images.insta_icon)
painter = painterResource(Res.drawable.insta_icon)
)
""".trimIndent()
)
Expand All @@ -142,13 +142,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Icon(
modifier = Modifier.size(140.dp),
bitmap = imageResource(Res.images.land),
bitmap = imageResource(Res.drawable.land),
contentDescription = null
)
Text(
"""
Icon(
bitmap = imageResource(Res.images.land)
bitmap = imageResource(Res.drawable.land)
)
""".trimIndent()
)
Expand All @@ -161,13 +161,13 @@ fun ImagesRes(contentPadding: PaddingValues) {
) {
Icon(
modifier = Modifier.size(100.dp),
imageVector = vectorResource(Res.images.droid_icon),
imageVector = vectorResource(Res.drawable.droid_icon),
contentDescription = null
)
Text(
"""
Icon(
imageVector = vectorResource(Res.images.droid_icon)
imageVector = vectorResource(Res.drawable.droid_icon)
)
""".trimIndent()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import components.resources.demo.generated.resources.Res
import org.jetbrains.compose.resources.getString
import org.jetbrains.compose.resources.getStringArray
import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.resources.stringArrayResource
import org.jetbrains.compose.resources.readResourceBytes

@Composable
Expand Down Expand Up @@ -54,9 +54,9 @@ fun StringRes(paddingValues: PaddingValues) {
}
OutlinedTextField(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
value = getString(Res.strings.app_name),
value = stringResource(Res.string.app_name),
onValueChange = {},
label = { Text("Text(getString(Res.strings.app_name)") },
label = { Text("Text(stringResource(Res.string.app_name)") },
enabled = false,
colors = TextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
Expand All @@ -66,9 +66,9 @@ fun StringRes(paddingValues: PaddingValues) {
)
OutlinedTextField(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
value = getString(Res.strings.hello),
value = stringResource(Res.string.hello),
onValueChange = {},
label = { Text("Text(getString(Res.strings.hello)") },
label = { Text("Text(stringResource(Res.string.hello)") },
enabled = false,
colors = TextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
Expand All @@ -78,9 +78,9 @@ fun StringRes(paddingValues: PaddingValues) {
)
OutlinedTextField(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
value = getString(Res.strings.multi_line),
value = stringResource(Res.string.multi_line),
onValueChange = {},
label = { Text("Text(getString(Res.strings.multi_line)") },
label = { Text("Text(stringResource(Res.string.multi_line)") },
enabled = false,
colors = TextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
Expand All @@ -90,9 +90,9 @@ fun StringRes(paddingValues: PaddingValues) {
)
OutlinedTextField(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
value = getString(Res.strings.str_template, "User_name", 100),
value = stringResource(Res.string.str_template, "User_name", 100),
onValueChange = {},
label = { Text("Text(getString(Res.strings.str_template, \"User_name\", 100)") },
label = { Text("Text(stringResource(Res.string.str_template, \"User_name\", 100)") },
enabled = false,
colors = TextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
Expand All @@ -102,9 +102,9 @@ fun StringRes(paddingValues: PaddingValues) {
)
OutlinedTextField(
modifier = Modifier.padding(16.dp).fillMaxWidth(),
value = getStringArray(Res.strings.str_arr).toString(),
value = stringArrayResource(Res.string.str_arr).toString(),
onValueChange = {},
label = { Text("Text(getStringArray(Res.strings.str_arr).toString())") },
label = { Text("Text(stringArrayResource(Res.string.str_arr).toString())") },
enabled = false,
colors = TextFieldDefaults.colors(
disabledTextColor = MaterialTheme.colorScheme.onSurface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

@OptIn(ExperimentalResourceApi::class, ExperimentalTestApi::class)
class ComposeResourceTest {
Expand All @@ -25,7 +26,7 @@ class ComposeResourceTest {
@Test
fun testCountRecompositions() = runComposeUiTest {
runBlockingTest {
val imagePathFlow = MutableStateFlow(ImageResource("1.png"))
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
val recompositionsCounter = RecompositionsCounter()
setContent {
val res by imagePathFlow.collectAsState()
Expand All @@ -35,7 +36,7 @@ class ComposeResourceTest {
}
}
awaitIdle()
imagePathFlow.emit(ImageResource("2.png"))
imagePathFlow.emit(DrawableResource("2.png"))
awaitIdle()
assertEquals(2, recompositionsCounter.count)
}
Expand All @@ -45,17 +46,17 @@ class ComposeResourceTest {
fun testImageResourceCache() = runComposeUiTest {
runBlockingTest {
val testResourceReader = TestResourceReader()
val imagePathFlow = MutableStateFlow(ImageResource("1.png"))
val imagePathFlow = MutableStateFlow(DrawableResource("1.png"))
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
val res by imagePathFlow.collectAsState()
Image(painterResource(res), null)
}
}
awaitIdle()
imagePathFlow.emit(ImageResource("2.png"))
imagePathFlow.emit(DrawableResource("2.png"))
awaitIdle()
imagePathFlow.emit(ImageResource("1.png"))
imagePathFlow.emit(DrawableResource("1.png"))
awaitIdle()

assertEquals(
Expand All @@ -73,8 +74,8 @@ class ComposeResourceTest {
setContent {
CompositionLocalProvider(LocalResourceReader provides testResourceReader) {
val res by stringIdFlow.collectAsState()
Text(getString(res))
Text(getStringArray(TestStringResource("str_arr")).joinToString())
Text(stringResource(res))
Text(stringArrayResource(TestStringResource("str_arr")).joinToString())
}
}
awaitIdle()
Expand All @@ -94,14 +95,56 @@ class ComposeResourceTest {
fun testReadStringResource() = runComposeUiTest {
runBlockingTest {
setContent {
assertEquals("Compose Resources App", getString(TestStringResource("app_name")))
assertEquals("Compose Resources App", stringResource(TestStringResource("app_name")))
assertEquals(
"Hello, test-name! You have 42 new messages.",
getString(TestStringResource("str_template"), "test-name", 42)
stringResource(TestStringResource("str_template"), "test-name", 42)
)
assertEquals(listOf("item 1", "item 2", "item 3"), getStringArray(TestStringResource("str_arr")))
assertEquals(listOf("item 1", "item 2", "item 3"), stringArrayResource(TestStringResource("str_arr")))
}
awaitIdle()
}
}

@Test
fun testLoadStringResource() = runBlockingTest {
kotlin.test.assertEquals("Compose Resources App", getString(TestStringResource("app_name")))
kotlin.test.assertEquals(
"Hello, test-name! You have 42 new messages.",
getString(TestStringResource("str_template"), "test-name", 42)
)
kotlin.test.assertEquals(listOf("item 1", "item 2", "item 3"), getStringArray(TestStringResource("str_arr")))
}

@Test
fun testMissingResource() = runBlockingTest {
assertFailsWith<MissingResourceException> {
readResourceBytes("missing.png")
}
val error = assertFailsWith<IllegalStateException> {
getString(TestStringResource("unknown_id"))
}
kotlin.test.assertEquals("String ID=`unknown_id` is not found!", error.message)
}

@Test
fun testReadFileResource() = runBlockingTest {
val bytes = readResourceBytes("strings.xml")
kotlin.test.assertEquals(
"""
<resources>
<string name="app_name">Compose Resources App</string>
<string name="hello">😊 Hello world!</string>
<string name="str_template">Hello, %1${'$'}s! You have %2${'$'}d new messages.</string>
<string-array name="str_arr">
<item>item 1</item>
<item>item 2</item>
<item>item 3</item>
</string-array>
</resources>

""".trimIndent(),
bytes.decodeToString()
)
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package org.jetbrains.compose.resources

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.font.*

@ExperimentalResourceApi
@Composable
actual fun Font(resource: FontResource, weight: FontWeight, style: FontStyle): Font {
val path = resource.getPathByEnvironment()
val environment = rememberEnvironment()
val path = remember(environment) { resource.getPathByEnvironment(environment) }
return Font(path, LocalContext.current.assets, weight, style)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jetbrains.compose.resources

import android.content.res.Configuration
import android.content.res.Resources
import java.util.*

internal actual fun getResourceEnvironment(): ResourceEnvironment {
val locale = Locale.getDefault()
val configuration = Resources.getSystem().configuration
val isDarkTheme = configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
val dpi = configuration.densityDpi
return ResourceEnvironment(
language = LanguageQualifier(locale.language),
region = RegionQualifier(locale.country),
theme = ThemeQualifier.selectByValue(isDarkTheme),
density = DensityQualifier.selectByValue(dpi)
)
}