Skip to content

Commit

Permalink
Merge pull request #1001 from believethehype/better_gallery_view
Browse files Browse the repository at this point in the history
Gallery: use FileHeader Info for rendering / faster loading
  • Loading branch information
vitorpamplona committed Jul 31, 2024
2 parents 2b2f04f + 8bca729 commit 4bae04a
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ open class Note(
var relays = listOf<RelayBriefInfoCache.RelayBriefInfo>()
private set

var associatedNote: Note? = null

var lastReactionsDownloadTime: Map<String, EOSETime> = emptyMap()

fun id() = Hex.decode(idHex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,69 @@ fun ZoomableContentView(
}
}

@Composable
fun GalleryContentView(
content: BaseMediaContent,
roundedCorner: Boolean,
isFiniteHeight: Boolean,
accountViewModel: AccountViewModel,
) {
when (content) {
is MediaUrlImage ->
SensitivityWarning(content.contentWarning != null, accountViewModel) {
TwoSecondController(content) { controllerVisible ->
val mainImageModifier = Modifier.fillMaxWidth()
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()

UrlImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel, gallery = true)
}
}
is MediaUrlVideo ->
SensitivityWarning(content.contentWarning != null, accountViewModel) {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
VideoView(
videoUri = content.url,
mimeType = content.mimeType,
title = content.description,
artworkUri = content.artworkUri,
gallery = true,
authorName = content.authorName,
dimensions = content.dim,
blurhash = content.blurhash,
roundedCorner = roundedCorner,
isFiniteHeight = isFiniteHeight,
nostrUriCallback = content.uri,
accountViewModel = accountViewModel,
)
}
}
is MediaLocalImage ->
TwoSecondController(content) { controllerVisible ->
val mainImageModifier = Modifier.fillMaxWidth()
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()

LocalImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel)
}
is MediaLocalVideo ->
content.localFile?.let {
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
VideoView(
videoUri = it.toUri().toString(),
mimeType = content.mimeType,
title = content.description,
artworkUri = content.artworkUri,
authorName = content.authorName,
gallery = true,
roundedCorner = roundedCorner,
isFiniteHeight = isFiniteHeight,
nostrUriCallback = content.uri,
accountViewModel = accountViewModel,
)
}
}
}
}

@Composable
fun TwoSecondController(
content: BaseMediaContent,
Expand Down Expand Up @@ -303,6 +366,7 @@ fun UrlImageView(
isFiniteHeight: Boolean,
controllerVisible: MutableState<Boolean>,
accountViewModel: AccountViewModel,
gallery: Boolean = false,
alwayShowImage: Boolean = false,
) {
Box(contentAlignment = Alignment.Center) {
Expand All @@ -319,7 +383,14 @@ fun UrlImageView(
SubcomposeAsyncImage(
model = content.url,
contentDescription = content.description,
contentScale = if (isFiniteHeight) ContentScale.Fit else ContentScale.FillWidth,
contentScale =
if (gallery) {
ContentScale.Crop
} else if (isFiniteHeight) {
ContentScale.Fit
} else {
ContentScale.FillWidth
},
modifier = mainImageModifier,
) {
when (painter.state) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,7 @@ class UserProfileGalleryFeedFilter(
}

var sorted = sort(notes)
var finalnotes = setOf<Note>()
for (item in sorted) {
val note = (item.event as ProfileGalleryEntryEvent).event()?.let { LocalCache.checkGetOrCreateNote(it) }
if (note != null) {
note.associatedNote = item
finalnotes = finalnotes + note
}
}

return finalnotes.toList()
return sorted.toList()
}

override fun applyFilter(collection: Set<Note>): Set<Note> = innerApplyFilter(collection)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,20 @@ import androidx.compose.ui.Alignment.Companion.BottomStart
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map
import coil.compose.AsyncImage
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser.Companion.isVideoUrl
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
import com.vitorpamplona.amethyst.ui.components.GalleryContentView
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
import com.vitorpamplona.amethyst.ui.components.VideoView
import com.vitorpamplona.amethyst.ui.note.CheckHiddenFeedWatchBlockAndReport
import com.vitorpamplona.amethyst.ui.note.ClickableNote
import com.vitorpamplona.amethyst.ui.note.LongPressToQuickActionGallery
Expand All @@ -79,7 +81,6 @@ import com.vitorpamplona.quartz.events.ProfileGalleryEntryEvent
fun RenderGalleryFeed(
viewModel: FeedViewModel,
routeForLastRead: String?,
forceEventKind: Int?,
listState: LazyGridState,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
Expand All @@ -103,7 +104,6 @@ fun RenderGalleryFeed(
state,
routeForLastRead,
listState,
forceEventKind,
accountViewModel,
nav,
)
Expand All @@ -121,7 +121,6 @@ private fun GalleryFeedLoaded(
state: FeedState.Loaded,
routeForLastRead: String?,
listState: LazyGridState,
forceEventKind: Int?,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
) {
Expand All @@ -138,7 +137,6 @@ private fun GalleryFeedLoaded(
baseNote = item,
routeForLastRead = routeForLastRead,
modifier = Modifier,
forceEventKind = forceEventKind,
accountViewModel = accountViewModel,
nav = nav,
)
Expand All @@ -157,7 +155,6 @@ fun GalleryCardCompose(
routeForLastRead: String? = null,
modifier: Modifier = Modifier,
parentBackgroundColor: MutableState<Color>? = null,
forceEventKind: Int?,
isHiddenFeed: Boolean = false,
accountViewModel: AccountViewModel,
nav: (String) -> Unit,
Expand All @@ -172,20 +169,29 @@ fun GalleryCardCompose(
nav = nav,
) { canPreview ->

if (baseNote.associatedNote != null) {
if (baseNote.associatedNote!!.event != null) {
val image = (baseNote.associatedNote!!.event as ProfileGalleryEntryEvent).url()
if (image != null) {
GalleryCard(
galleryNote = baseNote.associatedNote!!,
baseNote = baseNote,
image = image,
modifier = modifier,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
}
// TODO Vitor, this works, but maybe you know of a better way to run this here in the background
// as LocalCache.checkGetOrCreateNote(it) can not run on the main thread
var note: Note? = null
val thread =
Thread {
note = (baseNote.event as ProfileGalleryEntryEvent).event()?.let { LocalCache.checkGetOrCreateNote(it) }
}
thread.start()
thread.join()
// TODO End

val image = (baseNote.event as ProfileGalleryEntryEvent).url()
if (image != null) {
note?.let {
GalleryCard(
galleryNote = baseNote,
baseNote = it,
image = image,
modifier = modifier,
parentBackgroundColor = parentBackgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
}
}
}
Expand All @@ -206,6 +212,7 @@ fun GalleryCard(
LongPressToQuickActionGallery(baseNote = galleryNote, accountViewModel = accountViewModel) { showPopup ->
CheckNewAndRenderChannelCard(
baseNote,
galleryNote,
image,
modifier,
parentBackgroundColor,
Expand All @@ -219,6 +226,7 @@ fun GalleryCard(
@Composable
private fun CheckNewAndRenderChannelCard(
baseNote: Note,
galleryNote: Note,
image: String,
modifier: Modifier = Modifier,
parentBackgroundColor: MutableState<Color>? = null,
Expand All @@ -241,7 +249,7 @@ private fun CheckNewAndRenderChannelCard(
showPopup = showPopup,
nav = nav,
) {
InnerGalleryCardBox(baseNote, image, accountViewModel, nav)
InnerGalleryCardBox(galleryNote, image, accountViewModel, nav)
}
}

Expand All @@ -267,7 +275,6 @@ data class GalleryThumb(
val id: String?,
val image: String?,
val title: String?,
// val price: Price?,
)

@Composable
Expand All @@ -287,7 +294,6 @@ fun RenderGalleryThumb(
image = image,
title = "",
// noteEvent?.title(),
// price = noteEvent?.price(),
)
}.distinctUntilChanged()
.observeAsState(
Expand All @@ -298,7 +304,7 @@ fun RenderGalleryThumb(
),
)

InnerRenderGalleryThumb(card as GalleryThumb, baseNote, accountViewModel)
InnerRenderGalleryThumb(card, baseNote, accountViewModel)
}

@Preview
Expand All @@ -311,7 +317,6 @@ fun RenderGalleryThumbPreview(accountViewModel: AccountViewModel) {
id = "",
image = null,
title = "Like New",
// price = Price("800000", "SATS", null),
),
note = Note("hex"),
accountViewModel = accountViewModel,
Expand All @@ -332,27 +337,45 @@ fun InnerRenderGalleryThumb(
contentAlignment = BottomStart,
) {
card.image?.let {
var blurHash = (note.event as ProfileGalleryEntryEvent).blurhash()
var description = (note.event as ProfileGalleryEntryEvent).content
// var hash = (note.event as ProfileGalleryEntryEvent).hash()
var dimensions = (note.event as ProfileGalleryEntryEvent).dimensions()
var mimeType = (note.event as ProfileGalleryEntryEvent).mimeType()
var content: BaseMediaContent? = null

if (isVideoUrl(it)) {
VideoView(
videoUri = it,
mimeType = null,
title = "",
authorName = note.author?.toBestDisplayName(),
roundedCorner = false,
gallery = true,
isFiniteHeight = false,
alwaysShowVideo = true,
accountViewModel = accountViewModel,
)
content =
MediaUrlVideo(
url = it,
description = description,
hash = null,
blurhash = blurHash,
dim = dimensions,
uri = null,
mimeType = mimeType,
)
} else {
AsyncImage(
model = it,
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier.fillMaxSize(),
)
content =
MediaUrlImage(
url = it,
description = description,
hash = null, // We don't want to show the hash banner here
blurhash = blurHash,
dim = dimensions,
uri = null,
mimeType = mimeType,
)
}

GalleryContentView(
content = content,
roundedCorner = false,
isFiniteHeight = false,
accountViewModel = accountViewModel,
)
}
// }
?: run { DisplayGalleryAuthorBanner(note) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@ fun PrepareViewModels(
),
)

val galleryFeedViewModel: NostrUserProfileGalleryFeedViewModel =
viewModel(
key = baseUser.pubkeyHex + "UserGalleryFeedViewModel",
factory =
NostrUserProfileGalleryFeedViewModel.Factory(
baseUser,
accountViewModel.account,
),
)

val followersFeedViewModel: NostrUserProfileFollowersUserFeedViewModel =
viewModel(
key = baseUser.pubkeyHex + "UserProfileFollowersUserFeedViewModel",
Expand Down Expand Up @@ -298,16 +308,6 @@ fun PrepareViewModels(
),
)

val galleryFeedViewModel: NostrUserProfileGalleryFeedViewModel =
viewModel(
key = baseUser.pubkeyHex + "UserGalleryFeedViewModel",
factory =
NostrUserProfileGalleryFeedViewModel.Factory(
baseUser,
accountViewModel.account,
),
)

val reportsFeedViewModel: NostrUserProfileReportFeedViewModel =
viewModel(
key = baseUser.pubkeyHex + "UserProfileReportFeedViewModel",
Expand Down Expand Up @@ -1574,7 +1574,6 @@ fun TabGallery(
RenderGalleryFeed(
feedViewModel,
null,
0,
listState,
accountViewModel = accountViewModel,
nav = nav,
Expand Down

0 comments on commit 4bae04a

Please sign in to comment.