diff --git a/shared/src/androidMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt b/shared/src/androidMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt new file mode 100644 index 00000000..89b97be0 --- /dev/null +++ b/shared/src/androidMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt @@ -0,0 +1,20 @@ +package com.bumble.puzzyx.imageloader + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale + +@Composable +actual fun EmbeddableResourceImage( + path: String, + modifier: Modifier, + contentDescription: String?, + contentScale: ContentScale +) { + ResourceImage( + path = path, + modifier = modifier, + contentScale = contentScale, + contentDescription = contentDescription, + ) +} diff --git a/shared/src/commonMain/kotlin/com/bumble/puzzyx/composable/EntryCard.kt b/shared/src/commonMain/kotlin/com/bumble/puzzyx/composable/EntryCard.kt index 88c7e8f5..9e1db917 100644 --- a/shared/src/commonMain/kotlin/com/bumble/puzzyx/composable/EntryCard.kt +++ b/shared/src/commonMain/kotlin/com/bumble/puzzyx/composable/EntryCard.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.bumble.puzzyx.imageloader.ResourceImage +import com.bumble.puzzyx.imageloader.EmbeddableResourceImage import com.bumble.puzzyx.model.Entry import com.bumble.puzzyx.ui.colors @@ -33,7 +33,7 @@ fun EntryCard( ) { when (entry) { is Entry.Text -> TextEntry(entry) - is Entry.Image -> ResourceImage( + is Entry.Image -> EmbeddableResourceImage( path = "participant/${entry.path}", contentDescription = entry.contentDescription, contentScale = entry.contentScale, @@ -58,7 +58,7 @@ fun GitHubHeader( verticalAlignment = Alignment.CenterVertically, modifier = modifier ) { - ResourceImage( + EmbeddableResourceImage( path = "github.png", contentScale = ContentScale.Inside, modifier = Modifier diff --git a/shared/src/commonMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt b/shared/src/commonMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt index 871eeb95..ff9c72eb 100644 --- a/shared/src/commonMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt +++ b/shared/src/commonMain/kotlin/com/bumble/puzzyx/imageloader/ResourceImage.kt @@ -10,23 +10,45 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.layout.ContentScale +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import org.jetbrains.compose.resources.ExperimentalResourceApi import org.jetbrains.compose.resources.resource +@Composable +expect fun EmbeddableResourceImage( + path: String, + modifier: Modifier = Modifier, + contentDescription: String? = null, + contentScale: ContentScale = ContentScale.Fit, +) + @OptIn(ExperimentalResourceApi::class) @Composable -fun ResourceImage( +internal fun ResourceImage( path: String, + fallbackUrl: String = path, modifier: Modifier = Modifier, contentDescription: String? = null, contentScale: ContentScale = ContentScale.Fit ) { var image: ImageBitmap? by remember { mutableStateOf(null) } LaunchedEffect(Unit) { - image = - resource(path) - .readBytes() - .toImageBitmap() + image = withContext(Dispatchers.Default) { + try { + resource(path) + .readBytes() + .toImageBitmap() + } catch (e: Throwable) { + try { + resource(fallbackUrl) + .readBytes() + .toImageBitmap() + } catch (e: Throwable) { + null + } + } + } } image?.let { Image( diff --git a/shared/src/commonMain/kotlin/com/bumble/puzzyx/node/puzzle1/Puzzle1Node.kt b/shared/src/commonMain/kotlin/com/bumble/puzzyx/node/puzzle1/Puzzle1Node.kt index 591c5b9d..d9fee9ec 100644 --- a/shared/src/commonMain/kotlin/com/bumble/puzzyx/node/puzzle1/Puzzle1Node.kt +++ b/shared/src/commonMain/kotlin/com/bumble/puzzyx/node/puzzle1/Puzzle1Node.kt @@ -38,7 +38,7 @@ import com.bumble.puzzyx.appyx.component.gridpuzzle.operation.scatter import com.bumble.puzzyx.composable.AutoPlayScript import com.bumble.puzzyx.composable.EntryCardSmall import com.bumble.puzzyx.composable.FlashCard -import com.bumble.puzzyx.imageloader.ResourceImage +import com.bumble.puzzyx.imageloader.EmbeddableResourceImage import com.bumble.puzzyx.model.Entry import com.bumble.puzzyx.model.Puzzle import com.bumble.puzzyx.model.PuzzlePiece @@ -90,7 +90,7 @@ class Puzzle1Node( FlashCard( flash = Color.White, front = { modifier -> - ResourceImage( + EmbeddableResourceImage( path = "${puzzle.imagesDir}/slice_${puzzlePiece.j}_${puzzlePiece.i}.png", contentScale = ContentScale.FillBounds, modifier = modifier diff --git a/shared/src/desktopMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt b/shared/src/desktopMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt new file mode 100644 index 00000000..89b97be0 --- /dev/null +++ b/shared/src/desktopMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt @@ -0,0 +1,20 @@ +package com.bumble.puzzyx.imageloader + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale + +@Composable +actual fun EmbeddableResourceImage( + path: String, + modifier: Modifier, + contentDescription: String?, + contentScale: ContentScale +) { + ResourceImage( + path = path, + modifier = modifier, + contentScale = contentScale, + contentDescription = contentDescription, + ) +} diff --git a/shared/src/jsMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt b/shared/src/jsMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt new file mode 100644 index 00000000..6d0d2888 --- /dev/null +++ b/shared/src/jsMain/kotlin/com/bumble/puzzyx/imageloader/EmbeddableResourceImage.kt @@ -0,0 +1,23 @@ +package com.bumble.puzzyx.imageloader + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale + +private const val EMBED_URL = "appyx/where/hosted/sample" + +@Composable +actual fun EmbeddableResourceImage( + path: String, + modifier: Modifier, + contentDescription: String?, + contentScale: ContentScale +) { + ResourceImage( + path = EMBED_URL + path, + fallbackUrl = path, + modifier = modifier, + contentScale = contentScale, + contentDescription = contentDescription, + ) +}