diff --git a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt index 21b59f49d..a706ac80e 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/model/LocalCache.kt @@ -149,7 +149,7 @@ object LocalCache { val user = getOrCreateUser(event.pubKey.toHexKey()) 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( event.follows.map { try { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/AsyncImageProxy.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/AsyncImageProxy.kt new file mode 100644 index 000000000..b28ec20b4 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/AsyncImageProxy.kt @@ -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 + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt index 8f92d5cba..66ab816de 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/MainActivity.kt @@ -51,11 +51,6 @@ class MainActivity : ComponentActivity() { add(GifDecoder.Factory()) } add(SvgDecoder.Factory()) - }.diskCache { - DiskCache.Builder() - .directory(this.cacheDir.resolve("image_cache")) - .maxSizeBytes(1*1024*1024*1024) - .build() } .respectCacheHeaders(false) .build() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt index d5675ba76..cfc754d2c 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontStyle 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.relays.Client 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.NewUserMetadataView import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import java.net.URLEncoder import kotlinx.coroutines.launch @Composable @@ -209,8 +213,8 @@ fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel) }, modifier = Modifier ) { - AsyncImage( - model = accountUser.profilePicture(), + AsyncImageProxy( + model = ResizeImage(accountUser.profilePicture(), 34.dp), placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt index 71f448da9..edd142780 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt @@ -74,6 +74,8 @@ import androidx.compose.ui.graphics.PathFillType import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.platform.LocalContext import com.vitorpamplona.amethyst.RoboHashCache +import com.vitorpamplona.amethyst.ui.AsyncImageProxy +import com.vitorpamplona.amethyst.ui.ResizeImage @Composable fun DrawerContent(navController: NavHostController, @@ -132,8 +134,8 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol Box { val banner = accountUser.info.banner if (banner != null && banner.isNotBlank()) { - AsyncImage( - model = banner, + AsyncImageProxy( + model = ResizeImage(banner, 150.dp), contentDescription = "Profile Image", contentScale = ContentScale.FillWidth, modifier = Modifier @@ -152,8 +154,8 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol } Column(modifier = modifier) { - AsyncImage( - model = accountUser.profilePicture(), + AsyncImageProxy( + model = ResizeImage(accountUser.profilePicture(), 100.dp), contentDescription = "Profile Image", placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt index f3660d2b5..ab2008d9f 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt @@ -45,6 +45,8 @@ import com.vitorpamplona.amethyst.RoboHashCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent 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 @Composable @@ -150,8 +152,8 @@ fun ChannelName( ) { ChannelName( channelPicture = { - AsyncImage( - model = channelPicture, + AsyncImageProxy( + model = ResizeImage(channelPicture, 55.dp), placeholder = channelPicturePlaceholder, fallback = channelPicturePlaceholder, error = channelPicturePlaceholder, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt index 45eb813fd..f5b1033aa 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt @@ -61,6 +61,8 @@ import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent import com.vitorpamplona.amethyst.service.model.ReactionEvent 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.TranslateableRichTextViewer import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -161,8 +163,8 @@ fun ChatroomMessageCompose(baseNote: Note, routeForLastRead: String?, innerQuote horizontalArrangement = alignment, modifier = Modifier.padding(top = 5.dp) ) { - AsyncImage( - model = author.profilePicture(), + AsyncImageProxy( + model = ResizeImage(author.profilePicture(), 25.dp), placeholder = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)), @@ -287,8 +289,8 @@ private fun RelayBadges(baseNote: Note) { relaysToDisplay.forEach { val url = it.removePrefix("wss://") Box(Modifier.size(15.dp).padding(1.dp)) { - AsyncImage( - model = "https://${url}/favicon.ico", + AsyncImageProxy( + model = ResizeImage("https://${url}/favicon.ico", 15.dp), placeholder = BitmapPainter(RoboHashCache.get(ctx, url)), fallback = BitmapPainter(RoboHashCache.get(ctx, url)), error = BitmapPainter(RoboHashCache.get(ctx, url)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 46f390dab..33eb3f6d6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -69,6 +69,8 @@ import com.vitorpamplona.amethyst.service.model.LnZapEvent import com.vitorpamplona.amethyst.service.model.ReactionEvent import com.vitorpamplona.amethyst.service.model.ReportEvent 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.TranslateableRichTextViewer import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -195,8 +197,8 @@ fun NoteCompose( .width(30.dp) .height(30.dp) .align(Alignment.BottomEnd)) { - AsyncImage( - model = channel.profilePicture(), + AsyncImageProxy( + model = ResizeImage(channel.profilePicture(), 30.dp), placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)), fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)), error = BitmapPainter(RoboHashCache.get(context, channel.idHex)), @@ -338,8 +340,8 @@ private fun RelayBadges(baseNote: Note) { Modifier .size(15.dp) .padding(1.dp)) { - AsyncImage( - model = "https://${url}/favicon.ico", + AsyncImageProxy( + model = ResizeImage("https://${url}/favicon.ico", 15.dp), placeholder = BitmapPainter(RoboHashCache.get(ctx, url)), fallback = BitmapPainter(RoboHashCache.get(ctx, url)), error = BitmapPainter(RoboHashCache.get(ctx, url)), @@ -455,8 +457,8 @@ fun UserPicture( .width(size) .height(size)) { - AsyncImage( - model = user.profilePicture(), + AsyncImageProxy( + model = ResizeImage(user.profilePicture(), size), contentDescription = "Profile Image", placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt index 2b2ed5b79..0ae1d8044 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/qrcode/ShowQRDialog.kt @@ -38,6 +38,8 @@ import coil.compose.AsyncImage import coil.compose.rememberAsyncImagePainter import com.vitorpamplona.amethyst.RoboHashCache 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.qrcode.QrCodeScanner import nostr.postr.toNpub @@ -80,8 +82,8 @@ fun ShowQRDialog(user: User, onScan: (String) -> Unit, onClose: () -> Unit) { Column(modifier = Modifier.fillMaxWidth()) { Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) { - AsyncImage( - model = user.profilePicture(), + AsyncImageProxy( + model = ResizeImage(user.profilePicture(), 100.dp), placeholder = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, user.pubkeyHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt index 217b5f3af..7a0fa70a4 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt @@ -62,6 +62,8 @@ import com.vitorpamplona.amethyst.model.Channel import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.toNote 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.NewPostView import com.vitorpamplona.amethyst.ui.actions.PostButton @@ -158,8 +160,8 @@ fun ChannelHeader(baseChannel: Channel, account: Account, accountStateViewModel: Column(modifier = Modifier.padding(12.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - AsyncImage( - model = channel.profilePicture(), + AsyncImageProxy( + model = ResizeImage(channel.profilePicture(), 35.dp), placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)), fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)), error = BitmapPainter(RoboHashCache.get(context, channel.idHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt index 2f74e69c1..4afa325df 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt @@ -44,6 +44,8 @@ import coil.compose.rememberAsyncImagePainter import com.vitorpamplona.amethyst.RoboHashCache import com.vitorpamplona.amethyst.model.User 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.note.UserPicture 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 author = authorState?.user!! - AsyncImage( - model = author.profilePicture(), + AsyncImageProxy( + model = ResizeImage(author.profilePicture(), 35.dp), placeholder = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), fallback = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), error = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)), diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index 9aefa6f76..fe3b51fba 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -61,6 +61,8 @@ import com.vitorpamplona.amethyst.service.NostrUserProfileFollowersDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileFollowsDataSource import com.vitorpamplona.amethyst.service.NostrUserProfileZapsDataSource 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.components.InvoiceRequest import com.vitorpamplona.amethyst.ui.note.UserPicture @@ -427,8 +429,8 @@ private fun DrawBanner(baseUser: User) { val banner = user.info.banner if (banner != null && banner.isNotBlank()) { - AsyncImage( - model = banner, + AsyncImageProxy( + model = ResizeImage(banner, 125.dp), contentDescription = "Profile Image", contentScale = ContentScale.FillWidth, modifier = Modifier