Converts LiveData for Content-Sensitivity and Transitive Hidden Users into Flow to avoid locking the main thread while scrolling.
Requests flows on the Default thread.
This commit is contained in:
@@ -328,10 +328,10 @@ object LocalPreferences {
|
|||||||
)
|
)
|
||||||
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, account.hasDonatedInVersion)
|
putStringSet(PrefKeys.HAS_DONATED_IN_VERSION, account.hasDonatedInVersion)
|
||||||
|
|
||||||
if (account.showSensitiveContent == null) {
|
if (account.showSensitiveContent.value == null) {
|
||||||
remove(PrefKeys.SHOW_SENSITIVE_CONTENT)
|
remove(PrefKeys.SHOW_SENSITIVE_CONTENT)
|
||||||
} else {
|
} else {
|
||||||
putBoolean(PrefKeys.SHOW_SENSITIVE_CONTENT, account.showSensitiveContent!!)
|
putBoolean(PrefKeys.SHOW_SENSITIVE_CONTENT, account.showSensitiveContent.value!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
putString(
|
putString(
|
||||||
@@ -597,7 +597,7 @@ object LocalPreferences {
|
|||||||
backupContactList = latestContactList,
|
backupContactList = latestContactList,
|
||||||
proxy = proxy,
|
proxy = proxy,
|
||||||
proxyPort = proxyPort,
|
proxyPort = proxyPort,
|
||||||
showSensitiveContent = showSensitiveContent,
|
showSensitiveContent = MutableStateFlow(showSensitiveContent),
|
||||||
warnAboutPostsWithReports = warnAboutReports,
|
warnAboutPostsWithReports = warnAboutReports,
|
||||||
filterSpamFromStrangers = filterSpam,
|
filterSpamFromStrangers = filterSpam,
|
||||||
lastReadPerRoute = lastReadPerRoute,
|
lastReadPerRoute = lastReadPerRoute,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import androidx.compose.runtime.Immutable
|
|||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.asFlow
|
|
||||||
import androidx.lifecycle.asLiveData
|
import androidx.lifecycle.asLiveData
|
||||||
import androidx.lifecycle.liveData
|
import androidx.lifecycle.liveData
|
||||||
import androidx.lifecycle.switchMap
|
import androidx.lifecycle.switchMap
|
||||||
@@ -194,7 +193,7 @@ class Account(
|
|||||||
var backupContactList: ContactListEvent? = null,
|
var backupContactList: ContactListEvent? = null,
|
||||||
var proxy: Proxy? = null,
|
var proxy: Proxy? = null,
|
||||||
var proxyPort: Int = 9050,
|
var proxyPort: Int = 9050,
|
||||||
var showSensitiveContent: Boolean? = null,
|
var showSensitiveContent: MutableStateFlow<Boolean?> = MutableStateFlow(null),
|
||||||
var warnAboutPostsWithReports: Boolean = true,
|
var warnAboutPostsWithReports: Boolean = true,
|
||||||
var filterSpamFromStrangers: Boolean = true,
|
var filterSpamFromStrangers: Boolean = true,
|
||||||
var lastReadPerRoute: Map<String, Long> = mapOf<String, Long>(),
|
var lastReadPerRoute: Map<String, Long> = mapOf<String, Long>(),
|
||||||
@@ -202,7 +201,7 @@ class Account(
|
|||||||
var pendingAttestations: MutableStateFlow<Map<HexKey, String>> = MutableStateFlow<Map<HexKey, String>>(mapOf()),
|
var pendingAttestations: MutableStateFlow<Map<HexKey, String>> = MutableStateFlow<Map<HexKey, String>>(mapOf()),
|
||||||
val scope: CoroutineScope = Amethyst.instance.applicationIOScope,
|
val scope: CoroutineScope = Amethyst.instance.applicationIOScope,
|
||||||
) {
|
) {
|
||||||
var transientHiddenUsers: Set<String> = setOf()
|
var transientHiddenUsers: MutableStateFlow<Set<String>> = MutableStateFlow(setOf())
|
||||||
|
|
||||||
data class PaymentRequest(
|
data class PaymentRequest(
|
||||||
val relayUrl: String,
|
val relayUrl: String,
|
||||||
@@ -238,6 +237,8 @@ class Account(
|
|||||||
getPrivateOutboxRelayListFlow(),
|
getPrivateOutboxRelayListFlow(),
|
||||||
userProfile().flow().relays.stateFlow,
|
userProfile().flow().relays.stateFlow,
|
||||||
) { nip65RelayList, dmRelayList, searchRelayList, privateOutBox, userProfile ->
|
) { nip65RelayList, dmRelayList, searchRelayList, privateOutBox, userProfile ->
|
||||||
|
checkNotInMainThread()
|
||||||
|
|
||||||
val baseRelaySet = activeRelays() ?: convertLocalRelays()
|
val baseRelaySet = activeRelays() ?: convertLocalRelays()
|
||||||
val newDMRelaySet = (dmRelayList.note.event as? ChatMessageRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: emptySet()
|
val newDMRelaySet = (dmRelayList.note.event as? ChatMessageRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: emptySet()
|
||||||
val searchRelaySet = (searchRelayList.note.event as? SearchRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: Constants.defaultSearchRelaySet
|
val searchRelaySet = (searchRelayList.note.event as? SearchRelayListEvent)?.relays()?.map { RelayUrlFormatter.normalize(it) }?.toSet() ?: Constants.defaultSearchRelaySet
|
||||||
@@ -358,6 +359,7 @@ class Account(
|
|||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val liveKind3FollowsFlow: Flow<LiveFollowLists> =
|
val liveKind3FollowsFlow: Flow<LiveFollowLists> =
|
||||||
userProfile().flow().follows.stateFlow.transformLatest {
|
userProfile().flow().follows.stateFlow.transformLatest {
|
||||||
|
checkNotInMainThread()
|
||||||
emit(
|
emit(
|
||||||
LiveFollowLists(
|
LiveFollowLists(
|
||||||
it.user.cachedFollowingKeySet(),
|
it.user.cachedFollowingKeySet(),
|
||||||
@@ -394,6 +396,7 @@ class Account(
|
|||||||
peopleListFollowsSource: Flow<ListNameNotePair>,
|
peopleListFollowsSource: Flow<ListNameNotePair>,
|
||||||
): Flow<LiveFollowLists?> =
|
): Flow<LiveFollowLists?> =
|
||||||
combineTransform(kind3FollowsSource, peopleListFollowsSource) { kind3Follows, peopleListFollows ->
|
combineTransform(kind3FollowsSource, peopleListFollowsSource) { kind3Follows, peopleListFollows ->
|
||||||
|
checkNotInMainThread()
|
||||||
if (peopleListFollows.listName == GLOBAL_FOLLOWS) {
|
if (peopleListFollows.listName == GLOBAL_FOLLOWS) {
|
||||||
emit(null)
|
emit(null)
|
||||||
} else if (peopleListFollows.listName == KIND3_FOLLOWS) {
|
} else if (peopleListFollows.listName == KIND3_FOLLOWS) {
|
||||||
@@ -500,10 +503,11 @@ class Account(
|
|||||||
|
|
||||||
val flowHiddenUsers: StateFlow<LiveHiddenUsers> by lazy {
|
val flowHiddenUsers: StateFlow<LiveHiddenUsers> by lazy {
|
||||||
combineTransform(
|
combineTransform(
|
||||||
live.asFlow(),
|
transientHiddenUsers,
|
||||||
|
showSensitiveContent,
|
||||||
getBlockListNote().flow().metadata.stateFlow,
|
getBlockListNote().flow().metadata.stateFlow,
|
||||||
getMuteListNote().flow().metadata.stateFlow,
|
getMuteListNote().flow().metadata.stateFlow,
|
||||||
) { localLive, blockList, muteList ->
|
) { transientHiddenUsers, showSensitiveContent, blockList, muteList ->
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
val resultBlockList =
|
val resultBlockList =
|
||||||
@@ -532,8 +536,8 @@ class Account(
|
|||||||
LiveHiddenUsers(
|
LiveHiddenUsers(
|
||||||
hiddenUsers = (resultBlockList.users + resultMuteList.users),
|
hiddenUsers = (resultBlockList.users + resultMuteList.users),
|
||||||
hiddenWords = hiddenWords,
|
hiddenWords = hiddenWords,
|
||||||
spammers = localLive.account.transientHiddenUsers,
|
spammers = transientHiddenUsers,
|
||||||
showSensitiveContent = localLive.account.showSensitiveContent,
|
showSensitiveContent = showSensitiveContent,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}.stateIn(
|
}.stateIn(
|
||||||
@@ -542,8 +546,8 @@ class Account(
|
|||||||
LiveHiddenUsers(
|
LiveHiddenUsers(
|
||||||
hiddenUsers = setOf(),
|
hiddenUsers = setOf(),
|
||||||
hiddenWords = setOf(),
|
hiddenWords = setOf(),
|
||||||
spammers = transientHiddenUsers,
|
spammers = transientHiddenUsers.value,
|
||||||
showSensitiveContent = showSensitiveContent,
|
showSensitiveContent = showSensitiveContent.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -596,7 +600,9 @@ class Account(
|
|||||||
filterSpamFromStrangers = filterSpam
|
filterSpamFromStrangers = filterSpam
|
||||||
LocalCache.antiSpam.active = filterSpamFromStrangers
|
LocalCache.antiSpam.active = filterSpamFromStrangers
|
||||||
if (!filterSpamFromStrangers) {
|
if (!filterSpamFromStrangers) {
|
||||||
transientHiddenUsers = setOf()
|
transientHiddenUsers.update {
|
||||||
|
emptySet()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
live.invalidateData()
|
live.invalidateData()
|
||||||
saveable.invalidateData()
|
saveable.invalidateData()
|
||||||
@@ -2377,7 +2383,9 @@ class Account(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transientHiddenUsers = (transientHiddenUsers - pubkeyHex)
|
transientHiddenUsers.update {
|
||||||
|
it - pubkeyHex
|
||||||
|
}
|
||||||
live.invalidateData()
|
live.invalidateData()
|
||||||
saveable.invalidateData()
|
saveable.invalidateData()
|
||||||
}
|
}
|
||||||
@@ -2889,7 +2897,9 @@ class Account(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updateShowSensitiveContent(show: Boolean?) {
|
fun updateShowSensitiveContent(show: Boolean?) {
|
||||||
showSensitiveContent = show
|
showSensitiveContent.update {
|
||||||
|
show
|
||||||
|
}
|
||||||
saveable.invalidateData()
|
saveable.invalidateData()
|
||||||
live.invalidateData()
|
live.invalidateData()
|
||||||
}
|
}
|
||||||
@@ -2928,10 +2938,12 @@ class Account(
|
|||||||
// imports transient blocks due to spam.
|
// imports transient blocks due to spam.
|
||||||
LocalCache.antiSpam.liveSpam.observeForever {
|
LocalCache.antiSpam.liveSpam.observeForever {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
it.cache.spamMessages.snapshot().values.forEach {
|
it.cache.spamMessages.snapshot().values.forEach { spammer ->
|
||||||
if (it.pubkeyHex !in transientHiddenUsers && it.duplicatedMessages.size >= 5) {
|
if (spammer.pubkeyHex !in transientHiddenUsers.value && spammer.duplicatedMessages.size >= 5) {
|
||||||
if (it.pubkeyHex != userProfile().pubkeyHex && it.pubkeyHex !in followingKeySet()) {
|
if (spammer.pubkeyHex != userProfile().pubkeyHex && spammer.pubkeyHex !in followingKeySet()) {
|
||||||
transientHiddenUsers = (transientHiddenUsers + it.pubkeyHex)
|
transientHiddenUsers.update {
|
||||||
|
it + spammer.pubkeyHex
|
||||||
|
}
|
||||||
live.invalidateData()
|
live.invalidateData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,9 +179,7 @@ object Client : RelayPool.Listener {
|
|||||||
subscriptions = subscriptions.minus(subscriptionId)
|
subscriptions = subscriptions.minus(subscriptionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isActive(subscriptionId: String): Boolean {
|
fun isActive(subscriptionId: String): Boolean = subscriptions.contains(subscriptionId)
|
||||||
return subscriptions.contains(subscriptionId)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
override fun onEvent(
|
override fun onEvent(
|
||||||
@@ -205,9 +203,9 @@ object Client : RelayPool.Listener {
|
|||||||
) {
|
) {
|
||||||
// Releases the Web thread for the new payload.
|
// Releases the Web thread for the new payload.
|
||||||
// May need to add a processing queue if processing new events become too costly.
|
// May need to add a processing queue if processing new events become too costly.
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
// GlobalScope.launch(Dispatchers.Default) {
|
||||||
listeners.forEach { it.onRelayStateChange(type, relay, channel) }
|
listeners.forEach { it.onRelayStateChange(type, relay, channel) }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
@@ -249,21 +247,15 @@ object Client : RelayPool.Listener {
|
|||||||
listeners = listeners.plus(listener)
|
listeners = listeners.plus(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSubscribed(listener: Listener): Boolean {
|
fun isSubscribed(listener: Listener): Boolean = listeners.contains(listener)
|
||||||
return listeners.contains(listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun unsubscribe(listener: Listener) {
|
fun unsubscribe(listener: Listener) {
|
||||||
listeners = listeners.minus(listener)
|
listeners = listeners.minus(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allSubscriptions(): Map<String, List<TypedFilter>> {
|
fun allSubscriptions(): Map<String, List<TypedFilter>> = subscriptions
|
||||||
return subscriptions
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSubscriptionFilters(subId: String): List<TypedFilter> {
|
fun getSubscriptionFilters(subId: String): List<TypedFilter> = subscriptions[subId] ?: emptyList()
|
||||||
return subscriptions[subId] ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Listener {
|
abstract class Listener {
|
||||||
/** A new message was received */
|
/** A new message was received */
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
@@ -50,6 +49,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
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.compose.collectAsStateWithLifecycle
|
||||||
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.ui.actions.CrossfadeIfEnabled
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
@@ -97,10 +97,9 @@ fun SensitivityWarning(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
val accountState = accountViewModel.account.showSensitiveContent.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
var showContentWarningNote by
|
var showContentWarningNote by remember(accountState) { mutableStateOf(accountState.value != true) }
|
||||||
remember(accountState) { mutableStateOf(accountState?.account?.showSensitiveContent != true) }
|
|
||||||
|
|
||||||
CrossfadeIfEnabled(targetState = showContentWarningNote, accountViewModel = accountViewModel) {
|
CrossfadeIfEnabled(targetState = showContentWarningNote, accountViewModel = accountViewModel) {
|
||||||
if (it) {
|
if (it) {
|
||||||
@@ -118,18 +117,26 @@ fun ContentWarningNote(onDismiss: () -> Unit) {
|
|||||||
Column(modifier = Modifier.padding(start = 10.dp)) {
|
Column(modifier = Modifier.padding(start = 10.dp)) {
|
||||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
|
||||||
Box(
|
Box(
|
||||||
Modifier.height(80.dp).width(90.dp),
|
Modifier
|
||||||
|
.height(80.dp)
|
||||||
|
.width(90.dp),
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Visibility,
|
imageVector = Icons.Default.Visibility,
|
||||||
contentDescription = stringRes(R.string.content_warning),
|
contentDescription = stringRes(R.string.content_warning),
|
||||||
modifier = Modifier.size(70.dp).align(Alignment.BottomStart),
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.size(70.dp)
|
||||||
|
.align(Alignment.BottomStart),
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Rounded.Warning,
|
imageVector = Icons.Rounded.Warning,
|
||||||
contentDescription = stringRes(R.string.content_warning),
|
contentDescription = stringRes(R.string.content_warning),
|
||||||
modifier = Modifier.size(30.dp).align(Alignment.TopEnd),
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.size(30.dp)
|
||||||
|
.align(Alignment.TopEnd),
|
||||||
tint = MaterialTheme.colorScheme.onBackground,
|
tint = MaterialTheme.colorScheme.onBackground,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,15 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
|||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
|
|
||||||
class HiddenAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
|
class HiddenAccountsFeedFilter(
|
||||||
override fun feedKey(): String {
|
val account: Account,
|
||||||
return account.userProfile().pubkeyHex
|
) : FeedFilter<User>() {
|
||||||
}
|
override fun feedKey(): String = account.userProfile().pubkeyHex
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean {
|
override fun showHiddenKey(): Boolean = true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> =
|
||||||
return account.flowHiddenUsers.value.hiddenUsers.reversed().mapNotNull {
|
account.flowHiddenUsers.value.hiddenUsers.reversed().mapNotNull {
|
||||||
try {
|
try {
|
||||||
LocalCache.getOrCreateUser(it)
|
LocalCache.getOrCreateUser(it)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -45,33 +43,26 @@ class HiddenAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HiddenWordsFeedFilter(val account: Account) : FeedFilter<String>() {
|
class HiddenWordsFeedFilter(
|
||||||
override fun feedKey(): String {
|
val account: Account,
|
||||||
return account.userProfile().pubkeyHex
|
) : FeedFilter<String>() {
|
||||||
}
|
override fun feedKey(): String = account.userProfile().pubkeyHex
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean {
|
override fun showHiddenKey(): Boolean = true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun feed(): List<String> {
|
override fun feed(): List<String> =
|
||||||
return account.flowHiddenUsers.value.hiddenWords.toList()
|
account.flowHiddenUsers.value.hiddenWords
|
||||||
}
|
.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpammerAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
|
class SpammerAccountsFeedFilter(
|
||||||
override fun feedKey(): String {
|
val account: Account,
|
||||||
return account.userProfile().pubkeyHex
|
) : FeedFilter<User>() {
|
||||||
}
|
override fun feedKey(): String = account.userProfile().pubkeyHex
|
||||||
|
|
||||||
override fun showHiddenKey(): Boolean {
|
override fun showHiddenKey(): Boolean = true
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> = account.transientHiddenUsers.value.map { LocalCache.getOrCreateUser(it) }
|
||||||
return (account.transientHiddenUsers).map { LocalCache.getOrCreateUser(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ import com.vitorpamplona.amethyst.service.NostrSingleUserDataSource
|
|||||||
import com.vitorpamplona.amethyst.service.NostrThreadDataSource
|
import com.vitorpamplona.amethyst.service.NostrThreadDataSource
|
||||||
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
|
||||||
import com.vitorpamplona.amethyst.service.NostrVideoDataSource
|
import com.vitorpamplona.amethyst.service.NostrVideoDataSource
|
||||||
|
import com.vitorpamplona.amethyst.service.checkNotInMainThread
|
||||||
import com.vitorpamplona.amethyst.service.relays.Client
|
import com.vitorpamplona.amethyst.service.relays.Client
|
||||||
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
import com.vitorpamplona.amethyst.service.relays.RelayPool
|
||||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||||
@@ -758,6 +759,7 @@ class FollowListViewModel(
|
|||||||
|
|
||||||
private val _kind3GlobalPeopleRoutes =
|
private val _kind3GlobalPeopleRoutes =
|
||||||
combineTransform(livePeopleListsFlow, liveKind3FollowsFlow) { myLivePeopleListsFlow, myLiveKind3FollowsFlow ->
|
combineTransform(livePeopleListsFlow, liveKind3FollowsFlow) { myLivePeopleListsFlow, myLiveKind3FollowsFlow ->
|
||||||
|
checkNotInMainThread()
|
||||||
emit(
|
emit(
|
||||||
listOf(listOf(kind3Follow, globalFollow), myLivePeopleListsFlow, myLiveKind3FollowsFlow, listOf(muteListFollow))
|
listOf(listOf(kind3Follow, globalFollow), myLivePeopleListsFlow, myLiveKind3FollowsFlow, listOf(muteListFollow))
|
||||||
.flatten()
|
.flatten()
|
||||||
@@ -768,6 +770,7 @@ class FollowListViewModel(
|
|||||||
|
|
||||||
private val _kind3GlobalPeople =
|
private val _kind3GlobalPeople =
|
||||||
combineTransform(livePeopleListsFlow, liveKind3FollowsFlow) { myLivePeopleListsFlow, myLiveKind3FollowsFlow ->
|
combineTransform(livePeopleListsFlow, liveKind3FollowsFlow) { myLivePeopleListsFlow, myLiveKind3FollowsFlow ->
|
||||||
|
checkNotInMainThread()
|
||||||
emit(
|
emit(
|
||||||
listOf(listOf(kind3Follow, globalFollow), myLivePeopleListsFlow, listOf(muteListFollow))
|
listOf(listOf(kind3Follow, globalFollow), myLivePeopleListsFlow, listOf(muteListFollow))
|
||||||
.flatten()
|
.flatten()
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ fun WatchBookmarksFollowsAndAccount(
|
|||||||
isPublicBookmarkNote = accountViewModel.isInPublicBookmarks(note),
|
isPublicBookmarkNote = accountViewModel.isInPublicBookmarks(note),
|
||||||
isLoggedUser = accountViewModel.isLoggedUser(note.author),
|
isLoggedUser = accountViewModel.isLoggedUser(note.author),
|
||||||
isSensitive = note.event?.isSensitive() ?: false,
|
isSensitive = note.event?.isSensitive() ?: false,
|
||||||
showSensitiveContent = showSensitiveContent,
|
showSensitiveContent = showSensitiveContent.value,
|
||||||
)
|
)
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
|
|||||||
+11
-13
@@ -111,6 +111,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combineTransform
|
import kotlinx.coroutines.flow.combineTransform
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.joinAll
|
import kotlinx.coroutines.joinAll
|
||||||
@@ -308,22 +309,19 @@ class AccountViewModel(
|
|||||||
noteIsHiddenFlows.get(note)
|
noteIsHiddenFlows.get(note)
|
||||||
?: combineTransform(
|
?: combineTransform(
|
||||||
account.flowHiddenUsers,
|
account.flowHiddenUsers,
|
||||||
account.liveKind3FollowsFlow,
|
account.liveKind3Follows,
|
||||||
note.flow().metadata.stateFlow,
|
note.flow().metadata.stateFlow,
|
||||||
note.flow().reports.stateFlow,
|
note.flow().reports.stateFlow,
|
||||||
) { hiddenUsers, followingUsers, metadata, reports ->
|
) { hiddenUsers, followingUsers, metadata, reports ->
|
||||||
val isAcceptable =
|
emit(isNoteAcceptable(metadata.note, hiddenUsers, followingUsers.users))
|
||||||
withContext(Dispatchers.IO) {
|
}.flowOn(Dispatchers.Default)
|
||||||
isNoteAcceptable(metadata.note, hiddenUsers, followingUsers.users)
|
.stateIn(
|
||||||
}
|
viewModelScope,
|
||||||
emit(isAcceptable)
|
SharingStarted.Eagerly,
|
||||||
}.stateIn(
|
NoteComposeReportState(),
|
||||||
viewModelScope,
|
).also {
|
||||||
SharingStarted.Eagerly,
|
noteIsHiddenFlows.put(note, it)
|
||||||
NoteComposeReportState(),
|
}
|
||||||
).also {
|
|
||||||
noteIsHiddenFlows.put(note, it)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val noteMustShowExpandButtonFlows = LruCache<Note, StateFlow<Boolean>>(300)
|
private val noteMustShowExpandButtonFlows = LruCache<Note, StateFlow<Boolean>>(300)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user