Removes lazy StateFlows due to inconsistent starting values.

This commit is contained in:
Vitor Pamplona
2025-07-14 11:19:12 -04:00
parent 909eb62db6
commit 597fec5c43
15 changed files with 89 additions and 55 deletions
@@ -2266,7 +2266,7 @@ class Account(
val oldHashtags = contactList?.hashtags()?.toSet()
if (oldHashtags != null && oldHashtags.isNotEmpty()) {
Log.d("DB UPGRADE", "Migrating List with ${oldHashtags.size} old communities ")
Log.d("DB UPGRADE", "Migrating List with ${oldHashtags.size} old hashtags ")
val existingHashtags = hashtagList.flow.value
val needsToUpgrade = oldHashtags.filter { it !in existingHashtags }
@@ -63,8 +63,9 @@ class PrivateStorageRelayListState(
val flow =
getPrivateOutboxRelayListFlow()
.map { normalizePrivateOutboxRelayListWithBackup(it.note) }
.onStart { emit(normalizePrivateOutboxRelayListWithBackup(getPrivateOutboxRelayListNote())) }
.flowOn(Dispatchers.Default)
.onStart {
emit(normalizePrivateOutboxRelayListWithBackup(getPrivateOutboxRelayListNote()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
@@ -72,7 +72,7 @@ class EphemeralChatListState(
} ?: emptySet()
@OptIn(ExperimentalCoroutinesApi::class)
val liveEphemeralChatList: StateFlow<Set<RoomId>> by lazy {
val liveEphemeralChatList: StateFlow<Set<RoomId>> =
getEphemeralChatListFlow()
.transformLatest { noteState ->
emit(ephemeralChatListWithBackup(noteState.note))
@@ -84,7 +84,6 @@ class EphemeralChatListState(
SharingStarted.Eagerly,
emptySet(),
)
}
fun follow(
channel: EphemeralChatChannel,
@@ -81,11 +81,14 @@ class FollowListOutboxRelays(
emitAll(relayListFlows)
}.onStart {
val blocked = blockedRelayList.flow.value.toSet()
kind3Follows.flow.value.authors
.mapNotNull {
getNIP65RelayList(it)?.writeRelaysNorm()?.minus(blocked)
}.flatten()
.toSet()
val authors = kind3Follows.flow.value.authors
val perRelay =
authors
.mapNotNull {
getNIP65RelayList(it)?.writeRelaysNorm()?.minus(blocked)
}.flatten()
.toSet()
emit(perRelay)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -99,11 +102,13 @@ class FollowListOutboxRelays(
.map { relayList ->
relayList.map { it.url }.toSet()
}.onStart {
kind3Follows.flow.value.authors
.mapNotNull {
getNIP65RelayList(it)?.writeRelaysNorm()?.map { it.url }?.toSet()
}.flatten()
.toSet()
emit(
kind3Follows.flow.value.authors
.mapNotNull {
getNIP65RelayList(it)?.writeRelaysNorm()?.map { it.url }?.toSet()
}.flatten()
.toSet(),
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
@@ -71,6 +71,7 @@ class FollowListState(
.stateIn(
scope,
SharingStarted.Eagerly,
// this has priority.
buildKind3Follows(getFollowListEvent() ?: settings.backupContactList),
)
@@ -74,7 +74,7 @@ class PublicChatListState(
} ?: emptySet()
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<EventIdHint>> by lazy {
val flow: StateFlow<Set<EventIdHint>> =
getChannelListFlow()
.transformLatest { noteState ->
emit(publicChatListWithBackup(noteState.note))
@@ -86,20 +86,20 @@ class PublicChatListState(
SharingStarted.Eagerly,
emptySet(),
)
}
@OptIn(ExperimentalCoroutinesApi::class)
val flowSet: StateFlow<Set<HexKey>> by lazy {
val flowSet: StateFlow<Set<HexKey>> =
flow
.map {
it.mapTo(mutableSetOf()) { it.eventId }
}.onStart {
emit(flow.value.mapTo(mutableSetOf()) { it.eventId })
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
}
fun follow(
channel: PublicChatChannel,
@@ -38,6 +38,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
@@ -68,17 +69,18 @@ class EmojiPackState(
}
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<List<StateFlow<NoteState>>?> by lazy {
val flow: StateFlow<List<StateFlow<NoteState>>?> =
getEmojiPackSelectionFlow()
.transformLatest {
emit(convertEmojiSelectionPack(it.note.event as? EmojiPackSelectionEvent))
}.onStart {
emit(convertEmojiSelectionPack(getEmojiPackSelection()))
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
convertEmojiSelectionPack(getEmojiPackSelection()),
emptyList(),
)
}
fun convertEmojiPack(pack: EmojiPackEvent): List<EmojiMedia> =
pack.taggedEmojis().map {
@@ -98,7 +100,7 @@ class EmojiPackState(
.distinctBy { it.link }
@OptIn(ExperimentalCoroutinesApi::class)
val myEmojis by lazy {
val myEmojis =
flow
.transformLatest { emojiList ->
if (emojiList != null) {
@@ -110,13 +112,20 @@ class EmojiPackState(
} else {
emit(emptyList())
}
}.onStart {
emit(
mergePack(
convertEmojiSelectionPack(
getEmojiPackSelection(),
)?.map { it.value }?.toTypedArray() ?: emptyArray(),
),
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
mergePack(convertEmojiSelectionPack(getEmojiPackSelection())?.map { it.value }?.toTypedArray() ?: emptyArray()),
emptyList(),
)
}
fun addEmojiPack(
emojiPack: Note,
@@ -70,7 +70,7 @@ class GeohashListState(
} ?: emptySet()
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<String>> by lazy {
val flow: StateFlow<Set<String>> =
getGeohashListFlow()
.transformLatest { noteState ->
emit(geohashListWithBackup(noteState.note))
@@ -82,7 +82,6 @@ class GeohashListState(
SharingStarted.Eagerly,
emptySet(),
)
}
fun follow(
geohashs: List<String>,
@@ -70,7 +70,7 @@ class HashtagListState(
} ?: emptySet()
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<String>> by lazy {
val flow: StateFlow<Set<String>> =
getHashtagListFlow()
.transformLatest { noteState ->
emit(hashtagListWithBackup(noteState.note))
@@ -82,7 +82,6 @@ class HashtagListState(
SharingStarted.Eagerly,
emptySet(),
)
}
fun follow(
hashtags: List<String>,
@@ -33,9 +33,9 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking
class HiddenUsersState(
val muteList: StateFlow<PeopleListEvent.UsersAndWords>,
@@ -73,7 +73,7 @@ class HiddenUsersState(
showSensitiveContent = showSensitiveContent,
)
val flow: StateFlow<LiveHiddenUsers> by lazy {
val flow: StateFlow<LiveHiddenUsers> =
combineTransform(
blockList,
muteList,
@@ -82,20 +82,21 @@ class HiddenUsersState(
) { blockList, muteList, transientHiddenUsers, showSensitiveContent ->
checkNotInMainThread()
emit(assembleLiveHiddenUsers(blockList, muteList, transientHiddenUsers, showSensitiveContent))
}.onStart {
emit(
assembleLiveHiddenUsers(
blockList.value,
muteList.value,
transientHiddenUsers.value,
settings.syncedSettings.security.showSensitiveContent.value,
),
)
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
runBlocking {
assembleLiveHiddenUsers(
blockList.value,
muteList.value,
transientHiddenUsers.value,
settings.syncedSettings.security.showSensitiveContent.value,
)
},
LiveHiddenUsers(emptySet(), emptySet(), emptySet(), null),
)
}
fun resetTransientUsers() {
transientHiddenUsers.update {
@@ -73,7 +73,7 @@ class CommunityListState(
} ?: emptySet()
@OptIn(ExperimentalCoroutinesApi::class)
val flow: StateFlow<Set<AddressHint>> by lazy {
val flow: StateFlow<Set<AddressHint>> =
getCommunityListFlow()
.transformLatest { noteState ->
emit(communityListWithBackup(noteState.note))
@@ -85,20 +85,20 @@ class CommunityListState(
SharingStarted.Eagerly,
emptySet(),
)
}
@OptIn(ExperimentalCoroutinesApi::class)
val flowSet: StateFlow<Set<String>> by lazy {
val flowSet: StateFlow<Set<String>> =
flow
.map {
it.mapTo(mutableSetOf()) { it.addressId }
.map { hint ->
hint.mapTo(mutableSetOf()) { it.addressId }
}.onStart {
emit(flow.value.mapTo(mutableSetOf()) { it.addressId })
}.flowOn(Dispatchers.Default)
.stateIn(
scope,
SharingStarted.Eagerly,
emptySet(),
)
}
fun follow(
communities: List<AddressableNote>,
@@ -237,8 +237,14 @@ class FollowListState(
)
}
val kind3GlobalPeopleRoutes = _kind3GlobalPeopleRoutes.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.Eagerly, defaultLists)
val kind3GlobalPeople = _kind3GlobalPeople.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.Eagerly, defaultLists)
val kind3GlobalPeopleRoutes =
_kind3GlobalPeopleRoutes
.flowOn(Dispatchers.Default)
.stateIn(viewModelScope, SharingStarted.Eagerly, defaultLists)
val kind3GlobalPeople =
_kind3GlobalPeople
.flowOn(Dispatchers.Default)
.stateIn(viewModelScope, SharingStarted.Eagerly, defaultLists)
suspend fun initializeSuspend() {
checkNotInMainThread()
@@ -194,7 +194,10 @@ class AccountViewModel(
emit(newestItemCreatedAt != null && newestItemCreatedAt > lastRead)
}
val notificationHasNewItemsFlow = notificationHasNewItems.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.Eagerly, false)
val notificationHasNewItemsFlow =
notificationHasNewItems
.flowOn(Dispatchers.Default)
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
@OptIn(ExperimentalCoroutinesApi::class)
val messagesHasNewItems =
@@ -225,7 +228,10 @@ class AccountViewModel(
}
}
val messagesHasNewItemsFlow = messagesHasNewItems.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.Eagerly, false)
val messagesHasNewItemsFlow =
messagesHasNewItems
.flowOn(Dispatchers.Default)
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
@OptIn(ExperimentalCoroutinesApi::class)
val homeHasNewItems =
@@ -245,7 +251,10 @@ class AccountViewModel(
emit(newestItemCreatedAt != null && newestItemCreatedAt > lastRead)
}
val homeHasNewItemsFlow = homeHasNewItems.flowOn(Dispatchers.Default).stateIn(viewModelScope, SharingStarted.Eagerly, false)
val homeHasNewItemsFlow =
homeHasNewItems
.flowOn(Dispatchers.Default)
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
val hasNewItems =
mapOf(
@@ -359,6 +368,14 @@ class AccountViewModel(
note.flow().reports.stateFlow,
) { hiddenUsers, followingUsers, autor, metadata, reports ->
emit(isNoteAcceptable(metadata.note, hiddenUsers, followingUsers.authors))
}.onStart {
emit(
isNoteAcceptable(
note,
account.hiddenUsers.flow.value,
account.kind3FollowList.flow.value.authors,
),
)
}.flowOn(Dispatchers.Default)
.stateIn(
viewModelScope,
@@ -63,7 +63,7 @@ open class Event(
try {
fromJson(json)
} catch (e: Exception) {
Log.e("Event", "Unable to parse event JSON: $json", e)
Log.w("Event", "Unable to parse event JSON: $json", e)
null
}
@@ -41,7 +41,6 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.flow.stateIn
@@ -93,8 +92,6 @@ class NostrClient(
eventOutbox.relays,
) { reqs, counts, outbox ->
reqs + counts + outbox
}.onStart {
activeRequests.relays.value + activeCounts.relays.value + eventOutbox.relays.value
}.sample(300)
.onEach {
relayPool.updatePool(it)