mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-12 01:07:46 +00:00
Better rendering of Public Chats
This commit is contained in:
+7
-1
@@ -82,7 +82,13 @@ fun SensitivityWarning(
|
||||
accountViewModel: AccountViewModel,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
note.event?.let { SensitivityWarning(it, accountViewModel, content) }
|
||||
val noteEvent = note.event
|
||||
|
||||
if (noteEvent == null) {
|
||||
content()
|
||||
} else {
|
||||
SensitivityWarning(noteEvent, accountViewModel, content)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -21,23 +21,44 @@
|
||||
package com.vitorpamplona.amethyst.ui.note
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
|
||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||
import com.vitorpamplona.amethyst.ui.note.elements.BannerImage
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.theme.SimpleImageBorder
|
||||
|
||||
@Composable
|
||||
fun DisplayAuthorBanner(
|
||||
note: Note,
|
||||
baseNote: Note,
|
||||
accountViewModel: AccountViewModel,
|
||||
modifier: Modifier = SimpleImageBorder,
|
||||
) {
|
||||
WatchAuthor(note, accountViewModel) {
|
||||
val noteAuthor = baseNote.author
|
||||
if (noteAuthor != null) {
|
||||
BannerImage(
|
||||
it,
|
||||
noteAuthor,
|
||||
modifier,
|
||||
accountViewModel,
|
||||
)
|
||||
} else {
|
||||
val authorState by observeNote(baseNote, accountViewModel)
|
||||
CrossfadeIfEnabled(authorState.note.author, accountViewModel = accountViewModel) { author ->
|
||||
if (author != null) {
|
||||
BannerImage(
|
||||
author,
|
||||
modifier,
|
||||
accountViewModel,
|
||||
)
|
||||
} else {
|
||||
BannerImage(
|
||||
null as String?,
|
||||
modifier,
|
||||
accountViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,12 +154,11 @@ fun LoadPublicChatChannel(
|
||||
accountViewModel: AccountViewModel,
|
||||
content: @Composable (PublicChatChannel) -> Unit,
|
||||
) {
|
||||
val channel =
|
||||
produceStateIfNotNull(accountViewModel.getPublicChatChannelIfExists(id), id) {
|
||||
value = accountViewModel.checkGetOrCreatePublicChatChannel(id)
|
||||
}
|
||||
val channel by produceStateIfNotNull(accountViewModel.getPublicChatChannelIfExists(id), id) {
|
||||
value = accountViewModel.checkGetOrCreatePublicChatChannel(id)
|
||||
}
|
||||
|
||||
channel.value?.let { content(it) }
|
||||
channel?.let { content(it) }
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
+17
-23
@@ -119,38 +119,32 @@ fun BannerImage(
|
||||
if (!banner.isNullOrBlank()) {
|
||||
MyAsyncImage(
|
||||
imageUrl = banner,
|
||||
contentDescription =
|
||||
stringRes(
|
||||
R.string.preview_card_image_for,
|
||||
banner,
|
||||
),
|
||||
contentDescription = stringRes(R.string.preview_card_image_for, banner),
|
||||
contentScale = ContentScale.Crop,
|
||||
mainImageModifier = Modifier,
|
||||
loadedImageModifier = modifier,
|
||||
accountViewModel = accountViewModel,
|
||||
onLoadingBackground = {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.profile_banner, 4),
|
||||
contentDescription = stringRes(R.string.profile_banner),
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = modifier,
|
||||
)
|
||||
DefaultProfileBanner(modifier, 4)
|
||||
},
|
||||
onError = {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.profile_banner, 4),
|
||||
contentDescription = stringRes(R.string.profile_banner),
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = modifier,
|
||||
)
|
||||
DefaultProfileBanner(modifier, 4)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.profile_banner, 5),
|
||||
contentDescription = stringRes(R.string.profile_banner),
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = modifier,
|
||||
)
|
||||
DefaultProfileBanner(modifier, 5)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DefaultProfileBanner(
|
||||
modifier: Modifier,
|
||||
sizeReference: Int,
|
||||
) {
|
||||
Image(
|
||||
painter = painterRes(R.drawable.profile_banner, sizeReference),
|
||||
contentDescription = stringRes(R.string.profile_banner),
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
||||
+1
-4
@@ -68,7 +68,6 @@ import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||
import com.vitorpamplona.amethyst.ui.theme.RowColSpacing
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||
import com.vitorpamplona.amethyst.ui.theme.grayText
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
@@ -81,8 +80,6 @@ fun RenderPublicChatChannelThumb(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val noteEvent = baseNote.event as? ChannelCreateEvent ?: return
|
||||
|
||||
LoadPublicChatChannel(baseNote.idHex, accountViewModel) {
|
||||
RenderPublicChatChannelThumb(baseNote = baseNote, channel = it, accountViewModel, nav)
|
||||
}
|
||||
@@ -96,7 +93,7 @@ fun RenderPublicChatChannelThumb(
|
||||
nav: INav,
|
||||
) {
|
||||
val channelUpdates by observeChannel(channel, accountViewModel)
|
||||
val publicChat = channelUpdates?.channel as PublicChatChannel
|
||||
val publicChat = (channelUpdates?.channel as? PublicChatChannel) ?: channel
|
||||
|
||||
val name = remember(channelUpdates) { publicChat.toBestDisplayName() }
|
||||
val description = remember(channelUpdates) { publicChat.summary()?.ifBlank { null } }
|
||||
|
||||
+66
-18
@@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.publicChats
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@@ -45,15 +46,20 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||
import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.FeedState
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.Note
|
||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||
import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.note.CheckHiddenFeedWatchBlockAndReport
|
||||
import com.vitorpamplona.amethyst.ui.note.ClickableNote
|
||||
import com.vitorpamplona.amethyst.ui.note.LongPressToQuickAction
|
||||
import com.vitorpamplona.amethyst.ui.note.WatchNoteEvent
|
||||
import com.vitorpamplona.amethyst.ui.note.calculateBackgroundColor
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.ChannelCardCompose
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.RenderPublicChatChannelThumb
|
||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||
import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
|
||||
import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
||||
|
||||
@Composable
|
||||
fun PublicChatsFeedLoaded(
|
||||
@@ -66,12 +72,8 @@ fun PublicChatsFeedLoaded(
|
||||
val followedSet by accountViewModel.account.publicChatList.flowSet
|
||||
.collectAsStateWithLifecycle()
|
||||
|
||||
val pinned =
|
||||
remember(followedSet) {
|
||||
followedSet.mapNotNull { idHex ->
|
||||
LocalCache.getNoteIfExists(idHex)?.takeIf { it.event is ChannelCreateEvent }
|
||||
}
|
||||
}
|
||||
val pinned by accountViewModel.account.publicChatList.flowSetNote
|
||||
.collectAsStateWithLifecycle()
|
||||
|
||||
val unpinned =
|
||||
remember(items.list, followedSet) {
|
||||
@@ -91,7 +93,6 @@ fun PublicChatsFeedLoaded(
|
||||
items(
|
||||
pinned,
|
||||
key = { item -> "pinned-" + item.idHex },
|
||||
contentType = { item -> item.event?.kind ?: -1 },
|
||||
) { item ->
|
||||
PublicChatRow(item, pinned = true, accountViewModel, nav)
|
||||
}
|
||||
@@ -105,7 +106,6 @@ fun PublicChatsFeedLoaded(
|
||||
itemsIndexed(
|
||||
unpinned,
|
||||
key = { _, item -> item.idHex },
|
||||
contentType = { _, item -> item.event?.kind ?: -1 },
|
||||
) { _, item ->
|
||||
PublicChatRow(item, pinned = false, accountViewModel, nav)
|
||||
}
|
||||
@@ -114,20 +114,34 @@ fun PublicChatsFeedLoaded(
|
||||
|
||||
@Composable
|
||||
private fun LazyItemScope.PublicChatRow(
|
||||
item: Note,
|
||||
baseNote: Note,
|
||||
pinned: Boolean,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val modifier = Modifier.fillMaxWidth()
|
||||
|
||||
Box(Modifier.fillMaxWidth().animateItem()) {
|
||||
ChannelCardCompose(
|
||||
baseNote = item,
|
||||
routeForLastRead = "PublicChatsFeed",
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
forceEventKind = ChannelCreateEvent.KIND,
|
||||
WatchNoteEvent(
|
||||
baseNote = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
onBlank = {
|
||||
RenderChannel(baseNote, modifier, accountViewModel, nav)
|
||||
},
|
||||
onNoteEventFound = {
|
||||
CheckHiddenFeedWatchBlockAndReport(
|
||||
note = baseNote,
|
||||
modifier = modifier,
|
||||
ignoreAllBlocksAndReports = false,
|
||||
showHiddenWarning = false,
|
||||
accountViewModel = accountViewModel,
|
||||
nav = nav,
|
||||
) { _ ->
|
||||
RenderChannel(baseNote, modifier, accountViewModel, nav)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
if (pinned) {
|
||||
PinBadge(
|
||||
modifier =
|
||||
@@ -143,6 +157,40 @@ private fun LazyItemScope.PublicChatRow(
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RenderChannel(
|
||||
baseNote: Note,
|
||||
modifier: Modifier,
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
LongPressToQuickAction(baseNote, accountViewModel, nav) { showPopup ->
|
||||
ClickableNote(
|
||||
baseNote = baseNote,
|
||||
backgroundColor =
|
||||
calculateBackgroundColor(
|
||||
createdAt = baseNote.createdAt(),
|
||||
routeForLastRead = "PublicChatsFeed",
|
||||
parentBackgroundColor = null,
|
||||
accountViewModel = accountViewModel,
|
||||
),
|
||||
modifier = modifier,
|
||||
accountViewModel = accountViewModel,
|
||||
showPopup = showPopup,
|
||||
nav = nav,
|
||||
) {
|
||||
Column(StdPadding) {
|
||||
SensitivityWarning(
|
||||
note = baseNote,
|
||||
accountViewModel = accountViewModel,
|
||||
) {
|
||||
RenderPublicChatChannelThumb(baseNote, accountViewModel, nav)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PinBadge(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
|
||||
+14
@@ -36,6 +36,7 @@ import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
@@ -96,6 +97,19 @@ class PublicChatListState(
|
||||
emptySet(),
|
||||
)
|
||||
|
||||
val flowSetNote =
|
||||
flowSet
|
||||
.map {
|
||||
it.mapNotNull {
|
||||
cache.checkGetOrCreateNote(it)
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.Eagerly,
|
||||
emptyList(),
|
||||
)
|
||||
|
||||
suspend fun follow(channel: PublicChatChannel): ChannelListEvent {
|
||||
val publicChatList = getChannelList()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user