Moving livedata creation to long-lived objects
This commit is contained in:
@@ -3,6 +3,8 @@ package com.vitorpamplona.amethyst.model
|
|||||||
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
|
||||||
|
import androidx.lifecycle.distinctUntilChanged
|
||||||
|
import androidx.lifecycle.map
|
||||||
import com.vitorpamplona.amethyst.service.NostrSingleEventDataSource
|
import com.vitorpamplona.amethyst.service.NostrSingleEventDataSource
|
||||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.amethyst.service.firstFullCharOrEmoji
|
import com.vitorpamplona.amethyst.service.firstFullCharOrEmoji
|
||||||
@@ -10,6 +12,7 @@ import com.vitorpamplona.amethyst.service.relays.EOSETime
|
|||||||
import com.vitorpamplona.amethyst.service.relays.Relay
|
import com.vitorpamplona.amethyst.service.relays.Relay
|
||||||
import com.vitorpamplona.amethyst.ui.actions.updated
|
import com.vitorpamplona.amethyst.ui.actions.updated
|
||||||
import com.vitorpamplona.amethyst.ui.components.BundledUpdate
|
import com.vitorpamplona.amethyst.ui.components.BundledUpdate
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.combineWith
|
||||||
import com.vitorpamplona.amethyst.ui.note.toShortenHex
|
import com.vitorpamplona.amethyst.ui.note.toShortenHex
|
||||||
import com.vitorpamplona.quartz.encoders.ATag
|
import com.vitorpamplona.quartz.encoders.ATag
|
||||||
import com.vitorpamplona.quartz.encoders.Hex
|
import com.vitorpamplona.quartz.encoders.Hex
|
||||||
@@ -651,10 +654,18 @@ open class Note(val idHex: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
class NoteLiveSet(u: Note) {
|
class NoteLiveSet(u: Note) {
|
||||||
// Observers line up here.
|
// Observers line up here.
|
||||||
val metadata: NoteLiveData = NoteLiveData(u)
|
val metadata: NoteLiveData = NoteLiveData(u)
|
||||||
|
|
||||||
|
val authorChanges = metadata.map {
|
||||||
|
it.note.author
|
||||||
|
}
|
||||||
|
val hasEvent = metadata.map {
|
||||||
|
it.note.event != null
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
val reactions: NoteLiveData = NoteLiveData(u)
|
val reactions: NoteLiveData = NoteLiveData(u)
|
||||||
val boosts: NoteLiveData = NoteLiveData(u)
|
val boosts: NoteLiveData = NoteLiveData(u)
|
||||||
val replies: NoteLiveData = NoteLiveData(u)
|
val replies: NoteLiveData = NoteLiveData(u)
|
||||||
@@ -662,6 +673,20 @@ class NoteLiveSet(u: Note) {
|
|||||||
val relays: NoteLiveData = NoteLiveData(u)
|
val relays: NoteLiveData = NoteLiveData(u)
|
||||||
val zaps: NoteLiveData = NoteLiveData(u)
|
val zaps: NoteLiveData = NoteLiveData(u)
|
||||||
|
|
||||||
|
val hasReactions = zaps.combineWith(boosts, reactions) { zapState, boostState, reactionState ->
|
||||||
|
zapState?.note?.zaps?.isNotEmpty() ?: false ||
|
||||||
|
boostState?.note?.boosts?.isNotEmpty() ?: false ||
|
||||||
|
reactionState?.note?.reactions?.isNotEmpty() ?: false
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
|
val replyCount = replies.map {
|
||||||
|
it.note.replies.size
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
|
val boostCount = boosts.map {
|
||||||
|
it.note.boosts.size
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
fun isInUse(): Boolean {
|
fun isInUse(): Boolean {
|
||||||
return metadata.hasObservers() ||
|
return metadata.hasObservers() ||
|
||||||
reactions.hasObservers() ||
|
reactions.hasObservers() ||
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.vitorpamplona.amethyst.model
|
|||||||
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
|
||||||
|
import androidx.lifecycle.distinctUntilChanged
|
||||||
|
import androidx.lifecycle.map
|
||||||
import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource
|
import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource
|
||||||
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.amethyst.service.relays.EOSETime
|
import com.vitorpamplona.amethyst.service.relays.EOSETime
|
||||||
@@ -378,6 +380,7 @@ class User(val pubkeyHex: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
class UserLiveSet(u: User) {
|
class UserLiveSet(u: User) {
|
||||||
// UI Observers line up here.
|
// UI Observers line up here.
|
||||||
val follows: UserLiveData = UserLiveData(u)
|
val follows: UserLiveData = UserLiveData(u)
|
||||||
@@ -390,6 +393,14 @@ class UserLiveSet(u: User) {
|
|||||||
val zaps: UserLiveData = UserLiveData(u)
|
val zaps: UserLiveData = UserLiveData(u)
|
||||||
val bookmarks: UserLiveData = UserLiveData(u)
|
val bookmarks: UserLiveData = UserLiveData(u)
|
||||||
|
|
||||||
|
val profilePictureChanges = metadata.map {
|
||||||
|
it.user.profilePicture()
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
|
val userMetadataInfo = metadata.map {
|
||||||
|
it.user.info
|
||||||
|
}.distinctUntilChanged()
|
||||||
|
|
||||||
fun isInUse(): Boolean {
|
fun isInUse(): Boolean {
|
||||||
return follows.hasObservers() ||
|
return follows.hasObservers() ||
|
||||||
followers.hasObservers() ||
|
followers.hasObservers() ||
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ import androidx.compose.ui.unit.Constraints
|
|||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.em
|
import androidx.compose.ui.unit.em
|
||||||
import androidx.lifecycle.distinctUntilChanged
|
|
||||||
import androidx.lifecycle.map
|
|
||||||
import com.halilibo.richtext.markdown.Markdown
|
import com.halilibo.richtext.markdown.Markdown
|
||||||
import com.halilibo.richtext.markdown.MarkdownParseOptions
|
import com.halilibo.richtext.markdown.MarkdownParseOptions
|
||||||
import com.halilibo.richtext.ui.material.MaterialRichText
|
import com.halilibo.richtext.ui.material.MaterialRichText
|
||||||
@@ -421,9 +419,7 @@ private fun ObserveNIP19Event(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ObserveNote(note: Note, onRefresh: () -> Unit) {
|
fun ObserveNote(note: Note, onRefresh: () -> Unit) {
|
||||||
val loadedNoteId by note.live().metadata.map {
|
val loadedNoteId by note.live().metadata.observeAsState()
|
||||||
it.note.event?.id()
|
|
||||||
}.distinctUntilChanged().observeAsState(note.event?.id())
|
|
||||||
|
|
||||||
LaunchedEffect(key1 = loadedNoteId) {
|
LaunchedEffect(key1 = loadedNoteId) {
|
||||||
if (loadedNoteId != null) {
|
if (loadedNoteId != null) {
|
||||||
@@ -460,9 +456,7 @@ private fun ObserveNIP19User(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ObserveUser(user: User, onRefresh: () -> Unit) {
|
private fun ObserveUser(user: User, onRefresh: () -> Unit) {
|
||||||
val loadedUserMetaId by user.live().metadata.map {
|
val loadedUserMetaId by user.live().metadata.observeAsState()
|
||||||
it.user.info?.latestMetadata?.id
|
|
||||||
}.distinctUntilChanged().observeAsState(user.info?.latestMetadata?.id)
|
|
||||||
|
|
||||||
LaunchedEffect(key1 = loadedUserMetaId) {
|
LaunchedEffect(key1 = loadedUserMetaId) {
|
||||||
if (loadedUserMetaId != null) {
|
if (loadedUserMetaId != null) {
|
||||||
@@ -854,9 +848,7 @@ private fun DisplayUserFromTag(
|
|||||||
val route = remember { "User/${baseUser.pubkeyHex}" }
|
val route = remember { "User/${baseUser.pubkeyHex}" }
|
||||||
val hex = remember { baseUser.pubkeyDisplayHex() }
|
val hex = remember { baseUser.pubkeyDisplayHex() }
|
||||||
|
|
||||||
val meta by baseUser.live().metadata.map {
|
val meta by baseUser.live().userMetadataInfo.observeAsState(baseUser.info)
|
||||||
it.user.info
|
|
||||||
}.distinctUntilChanged().observeAsState(baseUser.info)
|
|
||||||
|
|
||||||
Crossfade(targetState = meta) {
|
Crossfade(targetState = meta) {
|
||||||
Row() {
|
Row() {
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.distinctUntilChanged
|
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.vitorpamplona.amethyst.BuildConfig
|
import com.vitorpamplona.amethyst.BuildConfig
|
||||||
@@ -484,7 +483,7 @@ private fun RelayStatus(
|
|||||||
relayViewModel: RelayPoolViewModel
|
relayViewModel: RelayPoolViewModel
|
||||||
) {
|
) {
|
||||||
val connectedRelaysText by relayViewModel.connectionStatus.observeAsState("--/--")
|
val connectedRelaysText by relayViewModel.connectionStatus.observeAsState("--/--")
|
||||||
val isConnected by relayViewModel.isConnected.distinctUntilChanged().observeAsState(false)
|
val isConnected by relayViewModel.isConnected.observeAsState(false)
|
||||||
|
|
||||||
RenderRelayStatus(connectedRelaysText, isConnected)
|
RenderRelayStatus(connectedRelaysText, isConnected)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,24 +93,10 @@ fun ChannelCardCompose(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val isBlank by baseNote.live().metadata.map {
|
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||||
it.note.event == null
|
|
||||||
}.distinctUntilChanged().observeAsState(baseNote.event == null)
|
|
||||||
|
|
||||||
Crossfade(targetState = isBlank) {
|
Crossfade(targetState = hasEvent) {
|
||||||
if (it) {
|
if (it) {
|
||||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
|
||||||
BlankNote(
|
|
||||||
remember {
|
|
||||||
modifier.combinedClickable(
|
|
||||||
onClick = { },
|
|
||||||
onLongClick = showPopup
|
|
||||||
)
|
|
||||||
},
|
|
||||||
false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
if (forceEventKind == null || baseNote.event?.kind() == forceEventKind) {
|
||||||
CheckHiddenChannelCardCompose(
|
CheckHiddenChannelCardCompose(
|
||||||
baseNote,
|
baseNote,
|
||||||
@@ -122,6 +108,18 @@ fun ChannelCardCompose(
|
|||||||
nav
|
nav
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||||
|
BlankNote(
|
||||||
|
remember {
|
||||||
|
modifier.combinedClickable(
|
||||||
|
onClick = { },
|
||||||
|
onLongClick = showPopup
|
||||||
|
)
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,14 +77,12 @@ fun ChatroomHeaderCompose(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val isBlank by baseNote.live().metadata.map {
|
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||||
it.note.event == null
|
|
||||||
}.observeAsState(baseNote.event == null)
|
|
||||||
|
|
||||||
if (isBlank) {
|
if (hasEvent) {
|
||||||
BlankNote(Modifier)
|
|
||||||
} else {
|
|
||||||
ChatroomComposeChannelOrUser(baseNote, accountViewModel, nav)
|
ChatroomComposeChannelOrUser(baseNote, accountViewModel, nav)
|
||||||
|
} else {
|
||||||
|
BlankNote(Modifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,12 +85,20 @@ fun ChatroomMessageCompose(
|
|||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
onWantsToReply: (Note) -> Unit
|
onWantsToReply: (Note) -> Unit
|
||||||
) {
|
) {
|
||||||
val isBlank by baseNote.live().metadata.map {
|
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||||
it.note.event == null
|
|
||||||
}.observeAsState(baseNote.event == null)
|
|
||||||
|
|
||||||
Crossfade(targetState = isBlank) {
|
Crossfade(targetState = hasEvent) {
|
||||||
if (it) {
|
if (it) {
|
||||||
|
CheckHiddenChatMessage(
|
||||||
|
baseNote,
|
||||||
|
routeForLastRead,
|
||||||
|
innerQuote,
|
||||||
|
parentBackgroundColor,
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
onWantsToReply
|
||||||
|
)
|
||||||
|
} else {
|
||||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||||
BlankNote(
|
BlankNote(
|
||||||
remember {
|
remember {
|
||||||
@@ -101,16 +109,6 @@ fun ChatroomMessageCompose(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
CheckHiddenChatMessage(
|
|
||||||
baseNote,
|
|
||||||
routeForLastRead,
|
|
||||||
innerQuote,
|
|
||||||
parentBackgroundColor,
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
onWantsToReply
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ import androidx.compose.ui.text.SpanStyle
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.lifecycle.distinctUntilChanged
|
|
||||||
import androidx.lifecycle.map
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
@@ -579,9 +577,7 @@ private fun WatchNoteAuthor(
|
|||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
onContent: @Composable (User?) -> Unit
|
onContent: @Composable (User?) -> Unit
|
||||||
) {
|
) {
|
||||||
val author by baseNote.live().metadata.map {
|
val author by baseNote.live().authorChanges.observeAsState(baseNote.author)
|
||||||
it.note.author
|
|
||||||
}.observeAsState(baseNote.author)
|
|
||||||
|
|
||||||
onContent(author)
|
onContent(author)
|
||||||
}
|
}
|
||||||
@@ -591,9 +587,7 @@ private fun WatchUserMetadata(
|
|||||||
author: User,
|
author: User,
|
||||||
onNewMetadata: @Composable (String?) -> Unit
|
onNewMetadata: @Composable (String?) -> Unit
|
||||||
) {
|
) {
|
||||||
val userProfile by author.live().metadata.map {
|
val userProfile by author.live().profilePictureChanges.observeAsState(author.profilePicture())
|
||||||
it.user.profilePicture()
|
|
||||||
}.distinctUntilChanged().observeAsState(author.profilePicture())
|
|
||||||
|
|
||||||
onNewMetadata(userProfile)
|
onNewMetadata(userProfile)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -223,24 +223,10 @@ fun NoteCompose(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val isBlank by baseNote.live().metadata.map {
|
val hasEvent by baseNote.live().hasEvent.observeAsState(baseNote.event != null)
|
||||||
it.note.event == null
|
|
||||||
}.distinctUntilChanged().observeAsState(baseNote.event == null)
|
|
||||||
|
|
||||||
Crossfade(targetState = isBlank) {
|
Crossfade(targetState = hasEvent) {
|
||||||
if (it) {
|
if (it) {
|
||||||
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
|
||||||
BlankNote(
|
|
||||||
remember {
|
|
||||||
modifier.combinedClickable(
|
|
||||||
onClick = { },
|
|
||||||
onLongClick = showPopup
|
|
||||||
)
|
|
||||||
},
|
|
||||||
isBoostedNote || isQuotedNote
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CheckHiddenNoteCompose(
|
CheckHiddenNoteCompose(
|
||||||
note = baseNote,
|
note = baseNote,
|
||||||
routeForLastRead = routeForLastRead,
|
routeForLastRead = routeForLastRead,
|
||||||
@@ -255,6 +241,18 @@ fun NoteCompose(
|
|||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
nav = nav
|
nav = nav
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
LongPressToQuickAction(baseNote = baseNote, accountViewModel = accountViewModel) { showPopup ->
|
||||||
|
BlankNote(
|
||||||
|
remember {
|
||||||
|
modifier.combinedClickable(
|
||||||
|
onClick = { },
|
||||||
|
onLongClick = showPopup
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isBoostedNote || isQuotedNote
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -414,14 +414,7 @@ private fun ReactionDetailGallery(
|
|||||||
val defaultBackgroundColor = MaterialTheme.colors.background
|
val defaultBackgroundColor = MaterialTheme.colors.background
|
||||||
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
|
val backgroundColor = remember { mutableStateOf<Color>(defaultBackgroundColor) }
|
||||||
|
|
||||||
val hasReactions by baseNote.live().zaps.combineWith(
|
val hasReactions by baseNote.live().hasReactions.observeAsState(
|
||||||
baseNote.live().boosts,
|
|
||||||
baseNote.live().reactions
|
|
||||||
) { zapState, boostState, reactionState ->
|
|
||||||
zapState?.note?.zaps?.isNotEmpty() ?: false ||
|
|
||||||
boostState?.note?.boosts?.isNotEmpty() ?: false ||
|
|
||||||
reactionState?.note?.reactions?.isNotEmpty() ?: false
|
|
||||||
}.distinctUntilChanged().observeAsState(
|
|
||||||
baseNote.zaps.isNotEmpty() || baseNote.boosts.isNotEmpty() || baseNote.reactions.isNotEmpty()
|
baseNote.zaps.isNotEmpty() || baseNote.boosts.isNotEmpty() || baseNote.reactions.isNotEmpty()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -594,9 +587,7 @@ fun ReplyReaction(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ReplyCounter(baseNote: Note, textColor: Color) {
|
fun ReplyCounter(baseNote: Note, textColor: Color) {
|
||||||
val repliesState by baseNote.live().replies.map {
|
val repliesState by baseNote.live().replyCount.observeAsState(baseNote.replies.size)
|
||||||
it.note.replies.size
|
|
||||||
}.observeAsState(baseNote.replies.size)
|
|
||||||
|
|
||||||
SlidingAnimationCount(repliesState, textColor)
|
SlidingAnimationCount(repliesState, textColor)
|
||||||
}
|
}
|
||||||
@@ -731,9 +722,7 @@ fun BoostIcon(baseNote: Note, iconSize: Dp = Size20dp, grayTint: Color, accountV
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BoostText(baseNote: Note, grayTint: Color) {
|
fun BoostText(baseNote: Note, grayTint: Color) {
|
||||||
val boostState by baseNote.live().boosts.map {
|
val boostState by baseNote.live().boostCount.observeAsState(baseNote.boosts.size)
|
||||||
it.note.boosts.size
|
|
||||||
}.distinctUntilChanged().observeAsState(baseNote.boosts.size)
|
|
||||||
|
|
||||||
SlidingAnimationCount(boostState, grayTint)
|
SlidingAnimationCount(boostState, grayTint)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
@@ -187,10 +188,10 @@ class UserReactionsViewModel(val account: Account) : ViewModel() {
|
|||||||
private var takenIntoAccount = setOf<HexKey>()
|
private var takenIntoAccount = setOf<HexKey>()
|
||||||
private val sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd") // SimpleDateFormat()
|
private val sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd") // SimpleDateFormat()
|
||||||
|
|
||||||
val todaysReplyCount = _replies.map { showCount(it[today()]) }
|
val todaysReplyCount = _replies.map { showCount(it[today()]) }.distinctUntilChanged()
|
||||||
val todaysBoostCount = _boosts.map { showCount(it[today()]) }
|
val todaysBoostCount = _boosts.map { showCount(it[today()]) }.distinctUntilChanged()
|
||||||
val todaysReactionCount = _reactions.map { showCount(it[today()]) }
|
val todaysReactionCount = _reactions.map { showCount(it[today()]) }.distinctUntilChanged()
|
||||||
val todaysZapAmount = _zaps.map { showAmountAxis(it[today()]) }
|
val todaysZapAmount = _zaps.map { showAmountAxis(it[today()]) }.distinctUntilChanged()
|
||||||
|
|
||||||
fun formatDate(createAt: Long): String {
|
fun formatDate(createAt: Long): String {
|
||||||
return sdf.format(
|
return sdf.format(
|
||||||
|
|||||||
@@ -16,5 +16,5 @@ class RelayPoolViewModel : ViewModel() {
|
|||||||
|
|
||||||
val isConnected = RelayPool.live.map {
|
val isConnected = RelayPool.live.map {
|
||||||
it.relays.connectedRelays() > 0
|
it.relays.connectedRelays() > 0
|
||||||
}
|
}.distinctUntilChanged()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user