Activating Image Proxy + CDN

This commit is contained in:
Vitor Pamplona
2023-02-15 12:31:15 -05:00
parent 9ec9feda28
commit 3493802a1e
12 changed files with 131 additions and 32 deletions
@@ -149,7 +149,7 @@ object LocalCache {
val user = getOrCreateUser(event.pubKey.toHexKey()) val user = getOrCreateUser(event.pubKey.toHexKey())
if (event.createdAt > user.updatedFollowsAt) { if (event.createdAt > user.updatedFollowsAt) {
//Log.d("CL", "AAA ${user.toBestDisplayName()} ${event.follows.size}") Log.d("CL", "AAA ${user.toBestDisplayName()} ${event.follows.size}")
user.updateFollows( user.updateFollows(
event.follows.map { event.follows.map {
try { try {
@@ -0,0 +1,84 @@
package com.vitorpamplona.amethyst.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.compose.AsyncImagePainter
import coil.compose.LocalImageLoader
import java.net.URLEncoder
import java.util.Base64
data class ResizeImage(val url: String?, val size: Dp)
@Composable
fun AsyncImageProxy(
model: ResizeImage,
contentDescription: String?,
modifier: Modifier = Modifier,
placeholder: Painter? = null,
error: Painter? = null,
fallback: Painter? = error,
onLoading: ((AsyncImagePainter.State.Loading) -> Unit)? = null,
onSuccess: ((AsyncImagePainter.State.Success) -> Unit)? = null,
onError: ((AsyncImagePainter.State.Error) -> Unit)? = null,
alignment: Alignment = Alignment.Center,
contentScale: ContentScale = ContentScale.Fit,
alpha: Float = DefaultAlpha,
colorFilter: ColorFilter? = null,
filterQuality: FilterQuality = DrawScope.DefaultFilterQuality,
) {
if (model.url == null) {
AsyncImage(
model = model.url,
contentDescription = contentDescription,
imageLoader = LocalImageLoader.current,
modifier = modifier,
placeholder = placeholder,
error = error,
fallback = fallback,
onLoading = onLoading,
onSuccess = onSuccess,
onError = onError,
alignment = alignment,
contentScale = contentScale,
alpha = alpha,
colorFilter = colorFilter,
filterQuality = filterQuality
)
} else {
val imgPx = with(LocalDensity.current) { model.size.toPx().toInt() }
val base64 = Base64.getUrlEncoder().encodeToString(model.url.toByteArray())
val extension = model.url.split(".").lastOrNull()
println("https://d12fidohs5rlxk.cloudfront.net/preset:sharp/rs:fit:$imgPx:$imgPx:0/gravity:sm/$base64")
AsyncImage(
model = "https://d12fidohs5rlxk.cloudfront.net/preset:sharp/rs:fit:$imgPx:$imgPx:0/gravity:sm/$base64",
contentDescription = contentDescription,
imageLoader = LocalImageLoader.current,
modifier = modifier,
placeholder = placeholder,
error = error,
fallback = fallback,
onLoading = onLoading,
onSuccess = onSuccess,
onError = onError,
alignment = alignment,
contentScale = contentScale,
alpha = alpha,
colorFilter = colorFilter,
filterQuality = filterQuality
)
}
}
@@ -51,11 +51,6 @@ class MainActivity : ComponentActivity() {
add(GifDecoder.Factory()) add(GifDecoder.Factory())
} }
add(SvgDecoder.Factory()) add(SvgDecoder.Factory())
}.diskCache {
DiskCache.Builder()
.directory(this.cacheDir.resolve("image_cache"))
.maxSizeBytes(1*1024*1024*1024)
.build()
} }
.respectCacheHeaders(false) .respectCacheHeaders(false)
.build() .build()
@@ -36,6 +36,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -67,10 +68,13 @@ import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileZapsDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileZapsDataSource
import com.vitorpamplona.amethyst.service.relays.Client import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.service.relays.RelayPool import com.vitorpamplona.amethyst.service.relays.RelayPool
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import java.net.URLEncoder
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
@@ -209,8 +213,8 @@ fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel)
}, },
modifier = Modifier modifier = Modifier
) { ) {
AsyncImage( AsyncImageProxy(
model = accountUser.profilePicture(), model = ResizeImage(accountUser.profilePicture(), 34.dp),
placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
error = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
@@ -74,6 +74,8 @@ import androidx.compose.ui.graphics.PathFillType
import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import com.vitorpamplona.amethyst.RoboHashCache import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
@Composable @Composable
fun DrawerContent(navController: NavHostController, fun DrawerContent(navController: NavHostController,
@@ -132,8 +134,8 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol
Box { Box {
val banner = accountUser.info.banner val banner = accountUser.info.banner
if (banner != null && banner.isNotBlank()) { if (banner != null && banner.isNotBlank()) {
AsyncImage( AsyncImageProxy(
model = banner, model = ResizeImage(banner, 150.dp),
contentDescription = "Profile Image", contentDescription = "Profile Image",
contentScale = ContentScale.FillWidth, contentScale = ContentScale.FillWidth,
modifier = Modifier modifier = Modifier
@@ -152,8 +154,8 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol
} }
Column(modifier = modifier) { Column(modifier = modifier) {
AsyncImage( AsyncImageProxy(
model = accountUser.profilePicture(), model = ResizeImage(accountUser.profilePicture(), 100.dp),
contentDescription = "Profile Image", contentDescription = "Profile Image",
placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
@@ -45,6 +45,8 @@ import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@Composable @Composable
@@ -150,8 +152,8 @@ fun ChannelName(
) { ) {
ChannelName( ChannelName(
channelPicture = { channelPicture = {
AsyncImage( AsyncImageProxy(
model = channelPicture, model = ResizeImage(channelPicture, 55.dp),
placeholder = channelPicturePlaceholder, placeholder = channelPicturePlaceholder,
fallback = channelPicturePlaceholder, fallback = channelPicturePlaceholder,
error = channelPicturePlaceholder, error = channelPicturePlaceholder,
@@ -61,6 +61,8 @@ import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
import com.vitorpamplona.amethyst.service.model.ReactionEvent import com.vitorpamplona.amethyst.service.model.ReactionEvent
import com.vitorpamplona.amethyst.service.model.RepostEvent import com.vitorpamplona.amethyst.service.model.RepostEvent
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.components.RichTextViewer import com.vitorpamplona.amethyst.ui.components.RichTextViewer
import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -161,8 +163,8 @@ fun ChatroomMessageCompose(baseNote: Note, routeForLastRead: String?, innerQuote
horizontalArrangement = alignment, horizontalArrangement = alignment,
modifier = Modifier.padding(top = 5.dp) modifier = Modifier.padding(top = 5.dp)
) { ) {
AsyncImage( AsyncImageProxy(
model = author.profilePicture(), model = ResizeImage(author.profilePicture(), 25.dp),
placeholder = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
error = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
@@ -287,8 +289,8 @@ private fun RelayBadges(baseNote: Note) {
relaysToDisplay.forEach { relaysToDisplay.forEach {
val url = it.removePrefix("wss://") val url = it.removePrefix("wss://")
Box(Modifier.size(15.dp).padding(1.dp)) { Box(Modifier.size(15.dp).padding(1.dp)) {
AsyncImage( AsyncImageProxy(
model = "https://${url}/favicon.ico", model = ResizeImage("https://${url}/favicon.ico", 15.dp),
placeholder = BitmapPainter(RoboHashCache.get(ctx, url)), placeholder = BitmapPainter(RoboHashCache.get(ctx, url)),
fallback = BitmapPainter(RoboHashCache.get(ctx, url)), fallback = BitmapPainter(RoboHashCache.get(ctx, url)),
error = BitmapPainter(RoboHashCache.get(ctx, url)), error = BitmapPainter(RoboHashCache.get(ctx, url)),
@@ -69,6 +69,8 @@ import com.vitorpamplona.amethyst.service.model.LnZapEvent
import com.vitorpamplona.amethyst.service.model.ReactionEvent import com.vitorpamplona.amethyst.service.model.ReactionEvent
import com.vitorpamplona.amethyst.service.model.ReportEvent import com.vitorpamplona.amethyst.service.model.ReportEvent
import com.vitorpamplona.amethyst.service.model.RepostEvent import com.vitorpamplona.amethyst.service.model.RepostEvent
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.components.RichTextViewer import com.vitorpamplona.amethyst.ui.components.RichTextViewer
import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -195,8 +197,8 @@ fun NoteCompose(
.width(30.dp) .width(30.dp)
.height(30.dp) .height(30.dp)
.align(Alignment.BottomEnd)) { .align(Alignment.BottomEnd)) {
AsyncImage( AsyncImageProxy(
model = channel.profilePicture(), model = ResizeImage(channel.profilePicture(), 30.dp),
placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)), placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)), fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
error = BitmapPainter(RoboHashCache.get(context, channel.idHex)), error = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
@@ -338,8 +340,8 @@ private fun RelayBadges(baseNote: Note) {
Modifier Modifier
.size(15.dp) .size(15.dp)
.padding(1.dp)) { .padding(1.dp)) {
AsyncImage( AsyncImageProxy(
model = "https://${url}/favicon.ico", model = ResizeImage("https://${url}/favicon.ico", 15.dp),
placeholder = BitmapPainter(RoboHashCache.get(ctx, url)), placeholder = BitmapPainter(RoboHashCache.get(ctx, url)),
fallback = BitmapPainter(RoboHashCache.get(ctx, url)), fallback = BitmapPainter(RoboHashCache.get(ctx, url)),
error = BitmapPainter(RoboHashCache.get(ctx, url)), error = BitmapPainter(RoboHashCache.get(ctx, url)),
@@ -455,8 +457,8 @@ fun UserPicture(
.width(size) .width(size)
.height(size)) { .height(size)) {
AsyncImage( AsyncImageProxy(
model = user.profilePicture(), model = ResizeImage(user.profilePicture(), size),
contentDescription = "Profile Image", contentDescription = "Profile Image",
placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)),
@@ -38,6 +38,8 @@ import coil.compose.AsyncImage
import coil.compose.rememberAsyncImagePainter import coil.compose.rememberAsyncImagePainter
import com.vitorpamplona.amethyst.RoboHashCache import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.actions.CloseButton import com.vitorpamplona.amethyst.ui.actions.CloseButton
import com.vitorpamplona.amethyst.ui.qrcode.QrCodeScanner import com.vitorpamplona.amethyst.ui.qrcode.QrCodeScanner
import nostr.postr.toNpub import nostr.postr.toNpub
@@ -80,8 +82,8 @@ fun ShowQRDialog(user: User, onScan: (String) -> Unit, onClose: () -> Unit) {
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) { Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
AsyncImage( AsyncImageProxy(
model = user.profilePicture(), model = ResizeImage(user.profilePicture(), 100.dp),
placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)),
error = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)),
@@ -62,6 +62,8 @@ import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.toNote import com.vitorpamplona.amethyst.model.toNote
import com.vitorpamplona.amethyst.service.NostrChannelDataSource import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.actions.NewChannelView import com.vitorpamplona.amethyst.ui.actions.NewChannelView
import com.vitorpamplona.amethyst.ui.actions.NewPostView import com.vitorpamplona.amethyst.ui.actions.NewPostView
import com.vitorpamplona.amethyst.ui.actions.PostButton import com.vitorpamplona.amethyst.ui.actions.PostButton
@@ -158,8 +160,8 @@ fun ChannelHeader(baseChannel: Channel, account: Account, accountStateViewModel:
Column(modifier = Modifier.padding(12.dp)) { Column(modifier = Modifier.padding(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
AsyncImage( AsyncImageProxy(
model = channel.profilePicture(), model = ResizeImage(channel.profilePicture(), 35.dp),
placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)), placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)), fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
error = BitmapPainter(RoboHashCache.get(context, channel.idHex)), error = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
@@ -44,6 +44,8 @@ import coil.compose.rememberAsyncImagePainter
import com.vitorpamplona.amethyst.RoboHashCache import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrChatRoomDataSource import com.vitorpamplona.amethyst.service.NostrChatRoomDataSource
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.actions.PostButton import com.vitorpamplona.amethyst.ui.actions.PostButton
import com.vitorpamplona.amethyst.ui.note.UserPicture import com.vitorpamplona.amethyst.ui.note.UserPicture
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
@@ -141,8 +143,8 @@ fun ChatroomHeader(baseUser: User, accountViewModel: AccountViewModel, navContro
val authorState by baseUser.liveMetadata.observeAsState() val authorState by baseUser.liveMetadata.observeAsState()
val author = authorState?.user!! val author = authorState?.user!!
AsyncImage( AsyncImageProxy(
model = author.profilePicture(), model = ResizeImage(author.profilePicture(), 35.dp),
placeholder = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), placeholder = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
fallback = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
error = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
@@ -61,6 +61,8 @@ import com.vitorpamplona.amethyst.service.NostrUserProfileFollowersDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource
import com.vitorpamplona.amethyst.service.NostrUserProfileZapsDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileZapsDataSource
import com.vitorpamplona.amethyst.service.model.ReportEvent import com.vitorpamplona.amethyst.service.model.ReportEvent
import com.vitorpamplona.amethyst.ui.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.ResizeImage
import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
import com.vitorpamplona.amethyst.ui.components.InvoiceRequest import com.vitorpamplona.amethyst.ui.components.InvoiceRequest
import com.vitorpamplona.amethyst.ui.note.UserPicture import com.vitorpamplona.amethyst.ui.note.UserPicture
@@ -427,8 +429,8 @@ private fun DrawBanner(baseUser: User) {
val banner = user.info.banner val banner = user.info.banner
if (banner != null && banner.isNotBlank()) { if (banner != null && banner.isNotBlank()) {
AsyncImage( AsyncImageProxy(
model = banner, model = ResizeImage(banner, 125.dp),
contentDescription = "Profile Image", contentDescription = "Profile Image",
contentScale = ContentScale.FillWidth, contentScale = ContentScale.FillWidth,
modifier = Modifier modifier = Modifier