Skip to content

Commit

Permalink
Update images in Jetsnack example: host them locally and use Resource…
Browse files Browse the repository at this point in the history
…s library (#5131)

We used to rely on an external service to fetch the images. But they are
not available anymore
  • Loading branch information
eymar authored Sep 11, 2024
1 parent d2b934a commit 4c15625
Show file tree
Hide file tree
Showing 45 changed files with 131 additions and 97 deletions.
2 changes: 1 addition & 1 deletion examples/jetsnack/android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
android:allowBackup="false"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity android:name=".MainActivity" android:exported="true">
<activity android:name="com.example.android.MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Expand Down
1 change: 1 addition & 0 deletions examples/jetsnack/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ kotlin {
api(compose.runtime)
api(compose.foundation)
api(compose.material)
implementation(compose.components.resources)
implementation(libs.kotlinx.coroutines)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,69 @@
package com.example.jetsnack.ui.components

import androidx.compose.foundation.layout.fillMaxSize
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.example.jetsnack.R
import com.example.common.generated.resources.Res
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.compose.resources.ExperimentalResourceApi

private val imagesCache = mutableMapOf<String, ImageBitmap>()

@SuppressLint("UnusedContentLambdaTargetStateParameter")
@OptIn(ExperimentalAnimationApi::class, ExperimentalResourceApi::class)
@Composable
actual fun SnackAsyncImage(imageUrl: String, contentDescription: String?, modifier: Modifier) {
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(imageUrl)
.crossfade(true)
.build(),
contentDescription = contentDescription,
placeholder = painterResource(R.drawable.placeholder),
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
var img: ImageBitmap? by remember(imageUrl) { mutableStateOf(null) }


AnimatedContent(img, transitionSpec = {
fadeIn(TweenSpec()) with fadeOut(TweenSpec())
}) {
if (img != null) {
Image(img!!, contentDescription = contentDescription, modifier = modifier, contentScale = ContentScale.Crop)
} else {
Box(modifier = modifier)
}
}

LaunchedEffect(imageUrl) {
if (imagesCache.contains(imageUrl)) {
img = imagesCache[imageUrl]
} else {
withContext(Dispatchers.IO) {
img = try {
Res.readBytes(imageUrl).toAndroidBitmap().asImageBitmap().also {
imagesCache[imageUrl] = it
img = it
}
} catch (e: Throwable) {
e.printStackTrace()
null
}
}
}
}
}

fun ByteArray.toAndroidBitmap(): Bitmap {
return BitmapFactory.decodeByteArray(this, 0, size)
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,19 @@ private val searchCategoryCollections = listOf(
categories = listOf(
SearchCategory(
name = "Chips & crackers",
imageUrl = "https://source.unsplash.com/UsSdMZ78Q3E"
imageUrl = "files/chips.jpg"
),
SearchCategory(
name = "Fruit snacks",
imageUrl = "https://source.unsplash.com/SfP1PtM9Qa8"
imageUrl = "files/fruit.jpg"
),
SearchCategory(
name = "Desserts",
imageUrl = "https://source.unsplash.com/_jk8KIyN_uA"
imageUrl = "files/desserts.jpg"
),
SearchCategory(
name = "Nuts ",
imageUrl = "https://source.unsplash.com/UsSdMZ78Q3E"
imageUrl = "files/nuts.jpg"
)
)
),
Expand All @@ -87,27 +87,27 @@ private val searchCategoryCollections = listOf(
categories = listOf(
SearchCategory(
name = "Organic",
imageUrl = "https://source.unsplash.com/7meCnGCJ5Ms"
imageUrl = "files/organic.jpg"
),
SearchCategory(
name = "Gluten Free",
imageUrl = "https://source.unsplash.com/m741tj4Cz7M"
imageUrl = "files/gluten_free.jpg"
),
SearchCategory(
name = "Paleo",
imageUrl = "https://source.unsplash.com/dt5-8tThZKg"
imageUrl = "files/paleo.jpg"
),
SearchCategory(
name = "Vegan",
imageUrl = "https://source.unsplash.com/ReXxkS1m1H0"
imageUrl = "files/vegan.jpg"
),
SearchCategory(
name = "Vegitarian",
imageUrl = "https://source.unsplash.com/IGfIGP5ONV0"
imageUrl = "files/grapes.jpg"
),
SearchCategory(
name = "Whole30",
imageUrl = "https://source.unsplash.com/9MzCd76xLGk"
imageUrl = "files/popcorn.jpg"
)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.example.jetsnack.model

import androidx.compose.runtime.Immutable
import com.example.common.generated.resources.Res

@Immutable
data class Snack(
Expand All @@ -37,190 +38,190 @@ val snacks = listOf(
id = 1L,
name = "Cupcake",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/pGM4sjt_BdQ",
imageUrl = "files/cupcake.jpg",
price = 299
),
Snack(
id = 2L,
name = "Donut",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/Yc5sL-ejk6U",
imageUrl = "files/donut.jpg",
price = 290
),
Snack(
id = 3L,
name = "Eclair",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/-LojFX9NfPY",
imageUrl = "files/eclair.jpg",
price = 289
),
Snack(
id = 4L,
name = "Froyo",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/3U2V5WqK1PQ",
imageUrl = "files/froyo.jpg",
price = 288
),
Snack(
id = 5L,
name = "Gingerbread",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/Y4YR9OjdIMk",
imageUrl = "files/gingerbread.jpg",
price = 499
),
Snack(
id = 6L,
name = "Honeycomb",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/bELvIg_KZGU",
imageUrl = "files/honeycomb.jpg",
price = 309
),
Snack(
id = 7L,
name = "Ice Cream Sandwich",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/YgYJsFDd4AU",
imageUrl = "files/ice_cream_sandwich.jpg",
price = 1299
),
Snack(
id = 8L,
name = "Jellybean",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/0u_vbeOkMpk",
imageUrl = "files/jelly_bean.jpg",
price = 109
),
Snack(
id = 9L,
name = "KitKat",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/yb16pT5F_jE",
imageUrl = "files/kitkat.jpg",
price = 549
),
Snack(
id = 10L,
name = "Lollipop",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/AHF_ZktTL6Q",
imageUrl = "files/lollipop.jpg",
price = 209
),
Snack(
id = 11L,
name = "Marshmallow",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/rqFm0IgMVYY",
imageUrl = "files/marshmallow.jpg",
price = 219
),
Snack(
id = 12L,
name = "Nougat",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/qRE_OpbVPR8",
imageUrl = "files/nougat.jpg",
price = 309
),
Snack(
id = 13L,
name = "Oreo",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/33fWPnyN6tU",
imageUrl = "files/oreo.jpg",
price = 339
),
Snack(
id = 14L,
name = "Pie",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/aX_ljOOyWJY",
imageUrl = "files/pie.jpg",
price = 249
),
Snack(
id = 15L,
name = "Chips",
imageUrl = "https://source.unsplash.com/UsSdMZ78Q3E",
imageUrl = "files/chips.jpg",
price = 277
),
Snack(
id = 16L,
name = "Pretzels",
imageUrl = "https://source.unsplash.com/7meCnGCJ5Ms",
imageUrl = "files/pretzels.jpg",
price = 154
),
Snack(
id = 17L,
name = "Smoothies",
imageUrl = "https://source.unsplash.com/m741tj4Cz7M",
imageUrl = "files/smoothies.jpg",
price = 257
),
Snack(
id = 18L,
name = "Popcorn",
imageUrl = "https://source.unsplash.com/iuwMdNq0-s4",
imageUrl = "files/popcorn.jpg",
price = 167
),
Snack(
id = 19L,
name = "Almonds",
imageUrl = "https://source.unsplash.com/qgWWQU1SzqM",
imageUrl = "files/almonds.jpg",
price = 123
),
Snack(
id = 20L,
name = "Cheese",
imageUrl = "https://source.unsplash.com/9MzCd76xLGk",
imageUrl = "files/cheese.jpg",
price = 231
),
Snack(
id = 21L,
name = "Apples",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/1d9xXWMtQzQ",
imageUrl = "files/apples.jpg",
price = 221
),
Snack(
id = 22L,
name = "Apple sauce",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/wZxpOw84QTU",
imageUrl = "files/apple_sauce.jpg",
price = 222
),
Snack(
id = 23L,
name = "Apple chips",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/okzeRxm_GPo",
imageUrl = "files/apple_chips.jpg",
price = 231
),
Snack(
id = 24L,
name = "Apple juice",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/l7imGdupuhU",
imageUrl = "files/apple_juice.jpg",
price = 241
),
Snack(
id = 25L,
name = "Apple pie",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/bkXzABDt08Q",
imageUrl = "files/apple_pie.jpg",
price = 225
),
Snack(
id = 26L,
name = "Grapes",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/y2MeW00BdBo",
imageUrl = "files/grapes.jpg",
price = 266
),
Snack(
id = 27L,
name = "Kiwi",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/1oMGgHn-M8k",
imageUrl = "files/kiwi.jpg",
price = 127
),
Snack(
id = 28L,
name = "Mango",
tagline = "A tag line",
imageUrl = "https://source.unsplash.com/TIGDsyy0TK4",
imageUrl = "files/mango.jpg",
price = 128
)
)
Loading

0 comments on commit 4c15625

Please sign in to comment.