mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-06-29 10:49:00 +02:00
Memory improvements on relay lists and LiveData objects
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
package com.vitorpamplona.amethyst.model
|
package com.vitorpamplona.amethyst.model
|
||||||
|
|
||||||
|
import android.util.LruCache
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
@ -41,7 +42,6 @@ import com.vitorpamplona.quartz.events.RepostEvent
|
|||||||
import com.vitorpamplona.quartz.events.WrappedEvent
|
import com.vitorpamplona.quartz.events.WrappedEvent
|
||||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
@ -93,7 +93,7 @@ open class Note(val idHex: String) {
|
|||||||
var zapPayments = mapOf<Note, Note?>()
|
var zapPayments = mapOf<Note, Note?>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var relays = listOf<String>()
|
var relays = listOf<RelayBriefInfoCache.RelayBriefInfo>()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var lastReactionsDownloadTime: Map<String, EOSETime> = emptyMap()
|
var lastReactionsDownloadTime: Map<String, EOSETime> = emptyMap()
|
||||||
@ -110,13 +110,13 @@ open class Note(val idHex: String) {
|
|||||||
host.id,
|
host.id,
|
||||||
host.pubKey,
|
host.pubKey,
|
||||||
host.kind(),
|
host.kind(),
|
||||||
relays.firstOrNull()
|
relays.firstOrNull()?.url
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Nip19.createNEvent(idHex, author?.pubkeyHex, event?.kind(), relays.firstOrNull())
|
Nip19.createNEvent(idHex, author?.pubkeyHex, event?.kind(), relays.firstOrNull()?.url)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Nip19.createNEvent(idHex, author?.pubkeyHex, event?.kind(), relays.firstOrNull())
|
Nip19.createNEvent(idHex, author?.pubkeyHex, event?.kind(), relays.firstOrNull()?.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ open class Note(val idHex: String) {
|
|||||||
zaps = mapOf<Note, Note?>()
|
zaps = mapOf<Note, Note?>()
|
||||||
zapPayments = mapOf<Note, Note?>()
|
zapPayments = mapOf<Note, Note?>()
|
||||||
zapsAmount = BigDecimal.ZERO
|
zapsAmount = BigDecimal.ZERO
|
||||||
relays = listOf<String>()
|
relays = listOf<RelayBriefInfoCache.RelayBriefInfo>()
|
||||||
lastReactionsDownloadTime = emptyMap()
|
lastReactionsDownloadTime = emptyMap()
|
||||||
|
|
||||||
liveSet?.innerReplies?.invalidateData()
|
liveSet?.innerReplies?.invalidateData()
|
||||||
@ -428,15 +428,15 @@ open class Note(val idHex: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun addRelaySync(url: String) {
|
fun addRelaySync(briefInfo: RelayBriefInfoCache.RelayBriefInfo) {
|
||||||
if (url !in relays) {
|
if (briefInfo !in relays) {
|
||||||
relays = relays + url
|
relays = relays + briefInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addRelay(relay: Relay) {
|
fun addRelay(relay: Relay) {
|
||||||
if (relay.url !in relays) {
|
if (relay.brief !in relays) {
|
||||||
addRelaySync(relay.url)
|
addRelaySync(relay.brief)
|
||||||
liveSet?.innerRelays?.invalidateData()
|
liveSet?.innerRelays?.invalidateData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -870,14 +870,8 @@ class NoteLiveSet(u: Note) {
|
|||||||
it.note.boosts.size
|
it.note.boosts.size
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
val boostList = innerBoosts.map {
|
|
||||||
it.note.boosts.toImmutableList()
|
|
||||||
}.distinctUntilChanged()
|
|
||||||
|
|
||||||
val relayInfo = innerRelays.map {
|
val relayInfo = innerRelays.map {
|
||||||
it.note.relays.map {
|
it.note.relays
|
||||||
RelayBriefInfo(it)
|
|
||||||
}.toImmutableList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val content = innerMetadata.map {
|
val content = innerMetadata.map {
|
||||||
@ -897,8 +891,7 @@ class NoteLiveSet(u: Note) {
|
|||||||
hasReactions.hasObservers() ||
|
hasReactions.hasObservers() ||
|
||||||
replyCount.hasObservers() ||
|
replyCount.hasObservers() ||
|
||||||
reactionCount.hasObservers() ||
|
reactionCount.hasObservers() ||
|
||||||
boostCount.hasObservers() ||
|
boostCount.hasObservers()
|
||||||
boostList.hasObservers()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun destroy() {
|
fun destroy() {
|
||||||
@ -986,9 +979,22 @@ class NoteLoadingLiveData<Y>(val note: Note, initialValue: Y?) : MediatorLiveDat
|
|||||||
@Immutable
|
@Immutable
|
||||||
class NoteState(val note: Note)
|
class NoteState(val note: Note)
|
||||||
|
|
||||||
@Immutable
|
object RelayBriefInfoCache {
|
||||||
data class RelayBriefInfo(
|
val cache = LruCache<String, RelayBriefInfo?>(50)
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class RelayBriefInfo(
|
||||||
val url: String,
|
val url: String,
|
||||||
val displayUrl: String = url.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/").intern(),
|
val displayUrl: String = url.trim().removePrefix("wss://").removePrefix("ws://").removeSuffix("/").intern(),
|
||||||
val favIcon: String = "https://$displayUrl/favicon.ico".intern()
|
val favIcon: String = "https://$displayUrl/favicon.ico".intern()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun get(url: String): RelayBriefInfo {
|
||||||
|
val info = cache[url]
|
||||||
|
if (info != null) return info
|
||||||
|
|
||||||
|
val newInfo = RelayBriefInfo(url)
|
||||||
|
cache.put(url, newInfo)
|
||||||
|
return newInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -15,5 +15,5 @@ data class RelaySetupInfo(
|
|||||||
val feedTypes: Set<FeedType>,
|
val feedTypes: Set<FeedType>,
|
||||||
val paidRelay: Boolean = false
|
val paidRelay: Boolean = false
|
||||||
) {
|
) {
|
||||||
val briefInfo: RelayBriefInfo = RelayBriefInfo(url)
|
val briefInfo: RelayBriefInfoCache.RelayBriefInfo = RelayBriefInfoCache.RelayBriefInfo(url)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.vitorpamplona.amethyst.service.relays
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.vitorpamplona.amethyst.BuildConfig
|
import com.vitorpamplona.amethyst.BuildConfig
|
||||||
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.service.HttpClient
|
import com.vitorpamplona.amethyst.service.HttpClient
|
||||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.quartz.encoders.HexKey
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
@ -23,11 +24,13 @@ enum class FeedType {
|
|||||||
val COMMON_FEED_TYPES = setOf(FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.PRIVATE_DMS, FeedType.GLOBAL)
|
val COMMON_FEED_TYPES = setOf(FeedType.FOLLOWS, FeedType.PUBLIC_CHATS, FeedType.PRIVATE_DMS, FeedType.GLOBAL)
|
||||||
|
|
||||||
class Relay(
|
class Relay(
|
||||||
var url: String,
|
val url: String,
|
||||||
var read: Boolean = true,
|
val read: Boolean = true,
|
||||||
var write: Boolean = true,
|
val write: Boolean = true,
|
||||||
var activeTypes: Set<FeedType> = FeedType.values().toSet()
|
val activeTypes: Set<FeedType> = FeedType.values().toSet()
|
||||||
) {
|
) {
|
||||||
|
val brief = RelayBriefInfoCache.get(url)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// waits 3 minutes to reconnect once things fail
|
// waits 3 minutes to reconnect once things fail
|
||||||
const val RECONNECTING_IN_SECONDS = 60 * 3
|
const val RECONNECTING_IN_SECONDS = 60 * 3
|
||||||
|
@ -57,7 +57,7 @@ import androidx.compose.ui.window.DialogProperties
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
import com.vitorpamplona.amethyst.model.RelaySetupInfo
|
||||||
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
||||||
import com.vitorpamplona.amethyst.service.relays.Constants
|
import com.vitorpamplona.amethyst.service.relays.Constants
|
||||||
@ -329,7 +329,7 @@ fun ServerConfig(
|
|||||||
accountViewModel.retrieveRelayDocument(
|
accountViewModel.retrieveRelayDocument(
|
||||||
item.url,
|
item.url,
|
||||||
onInfo = {
|
onInfo = {
|
||||||
relayInfo = RelayInfoDialog(RelayBriefInfo(item.url), it)
|
relayInfo = RelayInfoDialog(RelayBriefInfoCache.RelayBriefInfo(item.url), it)
|
||||||
},
|
},
|
||||||
onError = { url, errorCode, exceptionMessage ->
|
onError = { url, errorCode, exceptionMessage ->
|
||||||
val msg = when (errorCode) {
|
val msg = when (errorCode) {
|
||||||
|
@ -26,7 +26,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.model.RelayInformation
|
import com.vitorpamplona.amethyst.model.RelayInformation
|
||||||
import com.vitorpamplona.amethyst.ui.components.ClickableEmail
|
import com.vitorpamplona.amethyst.ui.components.ClickableEmail
|
||||||
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
|
||||||
@ -43,7 +43,7 @@ import com.vitorpamplona.amethyst.ui.theme.StdPadding
|
|||||||
@Composable
|
@Composable
|
||||||
fun RelayInformationDialog(
|
fun RelayInformationDialog(
|
||||||
onClose: () -> Unit,
|
onClose: () -> Unit,
|
||||||
relayBriefInfo: RelayBriefInfo,
|
relayBriefInfo: RelayBriefInfoCache.RelayBriefInfo,
|
||||||
relayInfo: RelayInformation,
|
relayInfo: RelayInformation,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
|
@ -26,7 +26,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.model.RelayInformation
|
import com.vitorpamplona.amethyst.model.RelayInformation
|
||||||
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
||||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
import com.vitorpamplona.amethyst.service.relays.Relay
|
||||||
@ -37,12 +37,12 @@ import kotlinx.collections.immutable.toImmutableList
|
|||||||
|
|
||||||
data class RelayList(
|
data class RelayList(
|
||||||
val relay: Relay,
|
val relay: Relay,
|
||||||
val relayInfo: RelayBriefInfo,
|
val relayInfo: RelayBriefInfoCache.RelayBriefInfo,
|
||||||
val isSelected: Boolean
|
val isSelected: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
data class RelayInfoDialog(
|
data class RelayInfoDialog(
|
||||||
val relayBriefInfo: RelayBriefInfo,
|
val relayBriefInfo: RelayBriefInfoCache.RelayBriefInfo,
|
||||||
val relayInfo: RelayInformation
|
val relayInfo: RelayInformation
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ fun RelaySelectionDialog(
|
|||||||
accountViewModel.account.activeWriteRelays().map {
|
accountViewModel.account.activeWriteRelays().map {
|
||||||
RelayList(
|
RelayList(
|
||||||
relay = it,
|
relay = it,
|
||||||
relayInfo = RelayBriefInfo(it.url),
|
relayInfo = RelayBriefInfoCache.RelayBriefInfo(it.url),
|
||||||
isSelected = preSelectedList.any { relay -> it.url == relay.url }
|
isSelected = preSelectedList.any { relay -> it.url == relay.url }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -167,7 +167,12 @@ fun RelaySelectionDialog(
|
|||||||
accountViewModel.retrieveRelayDocument(
|
accountViewModel.retrieveRelayDocument(
|
||||||
item.relay.url,
|
item.relay.url,
|
||||||
onInfo = {
|
onInfo = {
|
||||||
relayInfo = RelayInfoDialog(RelayBriefInfo(item.relay.url), it)
|
relayInfo = RelayInfoDialog(
|
||||||
|
RelayBriefInfoCache.RelayBriefInfo(
|
||||||
|
item.relay.url
|
||||||
|
),
|
||||||
|
it
|
||||||
|
)
|
||||||
},
|
},
|
||||||
onError = { url, errorCode, exceptionMessage ->
|
onError = { url, errorCode, exceptionMessage ->
|
||||||
val msg = when (errorCode) {
|
val msg = when (errorCode) {
|
||||||
|
@ -56,7 +56,7 @@ class HomeNewThreadFeedFilter(val account: Account) : AdditiveFeedFilter<Note>()
|
|||||||
.asSequence()
|
.asSequence()
|
||||||
.filter { it ->
|
.filter { it ->
|
||||||
val noteEvent = it.event
|
val noteEvent = it.event
|
||||||
val isGlobalRelay = it.relays.any { gRelays.contains(it) }
|
val isGlobalRelay = it.relays.any { gRelays.contains(it.url) }
|
||||||
(noteEvent is TextNoteEvent || noteEvent is ClassifiedsEvent || noteEvent is RepostEvent || noteEvent is GenericRepostEvent || noteEvent is LongTextNoteEvent || noteEvent is PollNoteEvent || noteEvent is HighlightEvent || noteEvent is AudioTrackEvent || noteEvent is AudioHeaderEvent) &&
|
(noteEvent is TextNoteEvent || noteEvent is ClassifiedsEvent || noteEvent is RepostEvent || noteEvent is GenericRepostEvent || noteEvent is LongTextNoteEvent || noteEvent is PollNoteEvent || noteEvent is HighlightEvent || noteEvent is AudioTrackEvent || noteEvent is AudioHeaderEvent) &&
|
||||||
(!ignoreAddressables || noteEvent.kind() < 10000) &&
|
(!ignoreAddressables || noteEvent.kind() < 10000) &&
|
||||||
((isGlobal && isGlobalRelay) || it.author?.pubkeyHex in followingKeySet || noteEvent.isTaggedHashes(followingTagSet) || noteEvent.isTaggedGeoHashes(followingGeohashSet) || noteEvent.isTaggedAddressableNotes(followingCommunities)) &&
|
((isGlobal && isGlobalRelay) || it.author?.pubkeyHex in followingKeySet || noteEvent.isTaggedHashes(followingTagSet) || noteEvent.isTaggedGeoHashes(followingGeohashSet) || noteEvent.isTaggedAddressableNotes(followingCommunities)) &&
|
||||||
|
@ -44,6 +44,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.model.NoteState
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.ui.components.ImageUrlType
|
import com.vitorpamplona.amethyst.ui.components.ImageUrlType
|
||||||
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
|
import com.vitorpamplona.amethyst.ui.components.InLineIconRenderer
|
||||||
@ -303,6 +304,31 @@ fun RenderBoostGallery(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun RenderBoostGallery(
|
||||||
|
noteToGetBoostEvents: NoteState,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
accountViewModel: AccountViewModel
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = NotificationIconModifierSmaller
|
||||||
|
) {
|
||||||
|
RepostedIcon(
|
||||||
|
modifier = remember {
|
||||||
|
Modifier
|
||||||
|
.size(Size19dp)
|
||||||
|
.align(Alignment.TopEnd)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthorGallery(noteToGetBoostEvents, nav, accountViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MapZaps(
|
fun MapZaps(
|
||||||
zaps: ImmutableList<CombinedZap>,
|
zaps: ImmutableList<CombinedZap>,
|
||||||
@ -491,6 +517,22 @@ fun AuthorGallery(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
|
@Composable
|
||||||
|
fun AuthorGallery(
|
||||||
|
noteToGetBoostEvents: NoteState,
|
||||||
|
nav: (String) -> Unit,
|
||||||
|
accountViewModel: AccountViewModel
|
||||||
|
) {
|
||||||
|
Column(modifier = StdStartPadding) {
|
||||||
|
FlowRow() {
|
||||||
|
noteToGetBoostEvents.note.boosts.forEach { note ->
|
||||||
|
BoxedAuthor(note, nav, accountViewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BoxedAuthor(
|
private fun BoxedAuthor(
|
||||||
note: Note,
|
note: Note,
|
||||||
|
@ -88,7 +88,7 @@ import com.vitorpamplona.amethyst.R
|
|||||||
import com.vitorpamplona.amethyst.model.AddressableNote
|
import com.vitorpamplona.amethyst.model.AddressableNote
|
||||||
import com.vitorpamplona.amethyst.model.Channel
|
import com.vitorpamplona.amethyst.model.Channel
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
import com.vitorpamplona.amethyst.service.ReverseGeoLocationUtil
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
|
||||||
@ -1746,7 +1746,7 @@ fun DisplayRelaySet(
|
|||||||
|
|
||||||
val relays by remember(baseNote) {
|
val relays by remember(baseNote) {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
noteEvent.relays().map { RelayBriefInfo(it) }.toImmutableList()
|
noteEvent.relays().map { RelayBriefInfoCache.RelayBriefInfo(it) }.toImmutableList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,10 +406,10 @@ private fun WatchBoostsAndRenderGallery(
|
|||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
accountViewModel: AccountViewModel
|
accountViewModel: AccountViewModel
|
||||||
) {
|
) {
|
||||||
val boostsEvents by baseNote.live().boostList.observeAsState()
|
val boostsEvents by baseNote.live().boosts.observeAsState()
|
||||||
|
|
||||||
boostsEvents?.let {
|
boostsEvents?.let {
|
||||||
if (it.isNotEmpty()) {
|
if (it.note.boosts.isNotEmpty()) {
|
||||||
RenderBoostGallery(
|
RenderBoostGallery(
|
||||||
it,
|
it,
|
||||||
nav,
|
nav,
|
||||||
|
@ -11,8 +11,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
@ -20,17 +18,15 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonBoxModifer
|
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonBoxModifer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonIconButtonModifier
|
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonIconButtonModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonIconModifier
|
import com.vitorpamplona.amethyst.ui.theme.ShowMoreRelaysButtonIconModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
@ -39,16 +35,23 @@ fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String
|
|||||||
|
|
||||||
Spacer(DoubleVertSpacer)
|
Spacer(DoubleVertSpacer)
|
||||||
|
|
||||||
|
// FlowRow Seems to be a lot faster than LazyVerticalGrid
|
||||||
|
FlowRow() {
|
||||||
if (expanded) {
|
if (expanded) {
|
||||||
VerticalRelayPanelWithFlow(relayList, accountViewModel, nav)
|
relayList?.forEach {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val shortRelayList by remember {
|
relayList?.getOrNull(0)?.let {
|
||||||
derivedStateOf {
|
RenderRelay(it, accountViewModel, nav)
|
||||||
relayList.take(3).toImmutableList()
|
}
|
||||||
|
relayList?.getOrNull(1)?.let {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
relayList?.getOrNull(2)?.let {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VerticalRelayPanelWithFlow(shortRelayList, accountViewModel, nav)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relayList.size > 3 && !expanded) {
|
if (relayList.size > 3 && !expanded) {
|
||||||
@ -58,22 +61,6 @@ fun RelayBadges(baseNote: Note, accountViewModel: AccountViewModel, nav: (String
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
|
||||||
@Composable
|
|
||||||
@Stable
|
|
||||||
private fun VerticalRelayPanelWithFlow(
|
|
||||||
relays: ImmutableList<RelayBriefInfo>,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: (String) -> Unit
|
|
||||||
) {
|
|
||||||
// FlowRow Seems to be a lot faster than LazyVerticalGrid
|
|
||||||
FlowRow() {
|
|
||||||
relays.forEach { url ->
|
|
||||||
RenderRelay(url, accountViewModel, nav)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ShowMoreRelaysButton(onClick: () -> Unit) {
|
private fun ShowMoreRelaysButton(onClick: () -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
|
@ -34,7 +34,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.map
|
import androidx.lifecycle.map
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.RelayBriefInfo
|
import com.vitorpamplona.amethyst.model.RelayBriefInfoCache
|
||||||
import com.vitorpamplona.amethyst.model.RelayInformation
|
import com.vitorpamplona.amethyst.model.RelayInformation
|
||||||
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
import com.vitorpamplona.amethyst.service.Nip11Retriever
|
||||||
import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog
|
import com.vitorpamplona.amethyst.ui.actions.RelayInformationDialog
|
||||||
@ -46,7 +46,6 @@ import com.vitorpamplona.amethyst.ui.theme.Size15Modifier
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Size15dp
|
import com.vitorpamplona.amethyst.ui.theme.Size15dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdStartPadding
|
import com.vitorpamplona.amethyst.ui.theme.StdStartPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
public fun RelayBadgesHorizontal(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
public fun RelayBadgesHorizontal(baseNote: Note, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||||
@ -65,12 +64,21 @@ fun RenderRelayList(baseNote: Note, expanded: MutableState<Boolean>, accountView
|
|||||||
val noteRelays by baseNote.live().relayInfo.observeAsState()
|
val noteRelays by baseNote.live().relayInfo.observeAsState()
|
||||||
|
|
||||||
FlowRow(StdStartPadding, verticalArrangement = Arrangement.Center) {
|
FlowRow(StdStartPadding, verticalArrangement = Arrangement.Center) {
|
||||||
val relaysToDisplay = remember(noteRelays, expanded.value) {
|
if (expanded.value) {
|
||||||
if (expanded.value) noteRelays else noteRelays?.take(3)?.toImmutableList()
|
noteRelays?.forEach {
|
||||||
}
|
|
||||||
relaysToDisplay?.forEach {
|
|
||||||
RenderRelay(it, accountViewModel, nav)
|
RenderRelay(it, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
noteRelays?.getOrNull(0)?.let {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
noteRelays?.getOrNull(1)?.let {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
noteRelays?.getOrNull(2)?.let {
|
||||||
|
RenderRelay(it, accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +113,7 @@ fun ChatRelayExpandButton(onClick: () -> Unit) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RenderRelay(relay: RelayBriefInfo, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
fun RenderRelay(relay: RelayBriefInfoCache.RelayBriefInfo, accountViewModel: AccountViewModel, nav: (String) -> Unit) {
|
||||||
var relayInfo: RelayInformation? by remember { mutableStateOf(null) }
|
var relayInfo: RelayInformation? by remember { mutableStateOf(null) }
|
||||||
|
|
||||||
if (relayInfo != null) {
|
if (relayInfo != null) {
|
||||||
|
Reference in New Issue
Block a user