Modify the models to support creating a new list with several profiles. Use IO dispatcher in FollowSetState. Introduce follow set copying/cloning, with custom names/descriptions for the clones.

This commit is contained in:
KotlinGeekDev
2025-10-03 16:02:15 +01:00
parent 88fbee84dc
commit 2df575d4af
3 changed files with 55 additions and 22 deletions
@@ -25,20 +25,16 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent import com.vitorpamplona.quartz.nip51Lists.peopleList.PeopleListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class FollowSetState( class FollowSetState(
@@ -50,7 +46,7 @@ class FollowSetState(
private val isActive = MutableStateFlow(false) private val isActive = MutableStateFlow(false)
suspend fun getFollowSetNotes() = suspend fun getFollowSetNotes() =
withContext(Dispatchers.Default) { withContext(Dispatchers.IO) {
val followSetNotes = LocalCache.getFollowSetNotesFor(user) val followSetNotes = LocalCache.getFollowSetNotesFor(user)
return@withContext followSetNotes return@withContext followSetNotes
} }
@@ -63,7 +59,7 @@ class FollowSetState(
emit(followSets) emit(followSets)
delay(2000) delay(2000)
} }
}.flowOn(Dispatchers.Default) }.flowOn(Dispatchers.IO)
val profilesFlow = val profilesFlow =
getFollowSetNotesFlow() getFollowSetNotesFlow()
@@ -82,14 +78,5 @@ class FollowSetState(
init { init {
isActive.update { true } isActive.update { true }
scope.launch(Dispatchers.Default) {
getFollowSetNotesFlow()
.onCompletion {
isActive.update { false }
}.catch {
Log.e(this@FollowSetState.javaClass.simpleName, "Error on flow collection: ${it.message}")
isActive.update { false }
}.collect {}
}
} }
} }
@@ -129,7 +129,8 @@ class FollowSetFeedViewModel(
title = setName, title = setName,
description = setDescription, description = setDescription,
isPrivate = firstMemberShouldBePrivate, isPrivate = firstMemberShouldBePrivate,
firstMemberHex = optionalFirstMemberHex, firstPublicMembers = if (optionalFirstMemberHex != null) listOf(optionalFirstMemberHex) else emptyList(),
firstPrivateMembers = if (optionalFirstMemberHex != null) listOf(optionalFirstMemberHex) else emptyList(),
signer = account.signer, signer = account.signer,
) { ) {
account.sendMyPublicAndPrivateOutbox(it) account.sendMyPublicAndPrivateOutbox(it)
@@ -159,6 +160,31 @@ class FollowSetFeedViewModel(
} }
} }
fun cloneFollowSet(
currentFollowSet: FollowSet,
customCloneName: String?,
customCloneDescription: String?,
account: Account,
) {
if (!account.settings.isWriteable()) {
println("You are in read-only mode. Please login to make modifications.")
} else {
viewModelScope.launch(Dispatchers.IO) {
PeopleListEvent.createListWithDescription(
dTag = UUID.randomUUID().toString(),
title = customCloneName ?: currentFollowSet.title,
description = customCloneDescription ?: currentFollowSet.description,
isPrivate = false,
firstPublicMembers = currentFollowSet.publicProfiles.toList(),
firstPrivateMembers = currentFollowSet.privateProfiles.toList(),
signer = account.signer,
) {
account.sendMyPublicAndPrivateOutbox(it)
}
}
}
}
fun deleteFollowSet( fun deleteFollowSet(
followSet: FollowSet, followSet: FollowSet,
account: Account, account: Account,
@@ -223,18 +223,28 @@ class PeopleListEvent(
title: String, title: String,
description: String? = null, description: String? = null,
isPrivate: Boolean, isPrivate: Boolean,
firstMemberHex: String? = null, firstPublicMembers: List<String> = emptyList(),
firstPrivateMembers: List<String> = emptyList(),
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (PeopleListEvent) -> Unit, onReady: (PeopleListEvent) -> Unit,
) { ) {
val isFirstMemberSpecified = firstMemberHex != null
if (description == null) { if (description == null) {
val newListTemplate = val newListTemplate =
build( build(
name = title, name = title,
publicPeople = if (!isPrivate && isFirstMemberSpecified) listOf(UserTag(pubKey = firstMemberHex)) else emptyList(), publicPeople =
privatePeople = if (isPrivate && isFirstMemberSpecified) listOf(UserTag(pubKey = firstMemberHex)) else emptyList(), if (!isPrivate && firstPublicMembers.isNotEmpty()) {
firstPublicMembers.map { UserTag(pubKey = it) }
} else {
emptyList()
},
privatePeople =
if (isPrivate && firstPrivateMembers.isNotEmpty()) {
firstPrivateMembers.map { UserTag(pubKey = it) }
} else {
emptyList()
},
signer = signer, signer = signer,
dTag = dTag, dTag = dTag,
createdAt = createdAt, createdAt = createdAt,
@@ -245,8 +255,18 @@ class PeopleListEvent(
val event = val event =
build( build(
name = title, name = title,
publicPeople = if (!isPrivate && isFirstMemberSpecified) listOf(UserTag(pubKey = firstMemberHex)) else emptyList(), publicPeople =
privatePeople = if (isPrivate && isFirstMemberSpecified) listOf(UserTag(pubKey = firstMemberHex)) else emptyList(), if (!isPrivate && firstPublicMembers.isNotEmpty()) {
firstPublicMembers.map { UserTag(pubKey = it) }
} else {
emptyList()
},
privatePeople =
if (isPrivate && firstPrivateMembers.isNotEmpty()) {
firstPrivateMembers.map { UserTag(pubKey = it) }
} else {
emptyList()
},
signer = signer, signer = signer,
dTag = dTag, dTag = dTag,
createdAt = createdAt, createdAt = createdAt,