Fix some methods in LabeledBookmarkListsState. Add useful methods to LabeledBookmarkList and BookmarkGroupViewModel.

This commit is contained in:
KotlinGeekDev
2025-11-21 14:11:55 +01:00
parent c48436b0a6
commit 267d680ffc
3 changed files with 80 additions and 54 deletions
@@ -21,7 +21,9 @@
package com.vitorpamplona.amethyst.model.nip51Lists.labeledBookmarkLists package com.vitorpamplona.amethyst.model.nip51Lists.labeledBookmarkLists
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.EventBookmark
@Stable @Stable
data class LabeledBookmarkList( data class LabeledBookmarkList(
@@ -30,4 +32,12 @@ data class LabeledBookmarkList(
val description: String?, val description: String?,
val privateBookmarks: Set<BookmarkIdTag> = emptySet(), val privateBookmarks: Set<BookmarkIdTag> = emptySet(),
val publicBookmarks: Set<BookmarkIdTag> = emptySet(), val publicBookmarks: Set<BookmarkIdTag> = emptySet(),
) ) {
// TODO: Add methods for LInk and Hashtag, after their implementation.
val privatePostBookmarks = privateBookmarks.filter { it is EventBookmark }.map { bookmarkIdTag -> bookmarkIdTag as EventBookmark }
val publicPostBookmarks = publicBookmarks.filter { it is EventBookmark }.map { bookmarkIdTag -> bookmarkIdTag as EventBookmark }
val privateArticleBookmarks = privateBookmarks.filter { it is AddressBookmark }.map { bookmarkIdTag -> bookmarkIdTag as AddressBookmark }
val publicArticleBookmarks = publicBookmarks.filter { it is AddressBookmark }.map { bookmarkIdTag -> bookmarkIdTag as AddressBookmark }
}
@@ -98,6 +98,11 @@ class LabeledBookmarkListsState(
.flowOn(Dispatchers.IO) .flowOn(Dispatchers.IO)
.stateIn(scope, SharingStarted.Eagerly, emptyList()) .stateIn(scope, SharingStarted.Eagerly, emptyList())
fun List<LabeledBookmarkList>.getList(bookmarkListId: String) =
this.firstOrNull {
it.identifier == bookmarkListId
}
fun DeletionEvent.hasAnyDeletedBookmarkLists() = deleteAddressesWithKind(LabeledBookmarkListEvent.KIND) || deletesAnyEventIn(labeledBookmarkListEventIds.value) fun DeletionEvent.hasAnyDeletedBookmarkLists() = deleteAddressesWithKind(LabeledBookmarkListEvent.KIND) || deletesAnyEventIn(labeledBookmarkListEventIds.value)
fun hasItemInNoteList(notes: Set<Note>): Boolean = fun hasItemInNoteList(notes: Set<Note>): Boolean =
@@ -130,11 +135,11 @@ class LabeledBookmarkListsState(
fun getLabeledBookmarkListEvent(bookmarkIdentifier: String): LabeledBookmarkListEvent = getLabeledBookmarkListNote(bookmarkIdentifier)?.event as LabeledBookmarkListEvent fun getLabeledBookmarkListEvent(bookmarkIdentifier: String): LabeledBookmarkListEvent = getLabeledBookmarkListNote(bookmarkIdentifier)?.event as LabeledBookmarkListEvent
fun getLabeledBookmarkListFlow(bookmarkIdentifier: String) = fun getLabeledBookmarkListFlow(bookmarkIdentifier: String) =
labeledBookmarkListNotes listFeedFlow
.map { getLabeledBookmarkListEvent(bookmarkIdentifier).toLabeledBookmarkList() } .map { it.getList(bookmarkIdentifier) }
.onStart { .onStart {
emit( emit(
getLabeledBookmarkListEvent(bookmarkIdentifier).toLabeledBookmarkList(), listFeedFlow.value.getList(bookmarkIdentifier),
) )
}.flowOn(Dispatchers.IO) }.flowOn(Dispatchers.IO)
@@ -204,21 +209,22 @@ class LabeledBookmarkListsState(
} }
suspend fun deleteBookmarkList( suspend fun deleteBookmarkList(
bookmarkList: LabeledBookmarkList, bookmarkListIdentifier: String,
account: Account, account: Account,
) { ) {
val listEvent = getLabeledBookmarkListEvent(bookmarkList.identifier) val listEvent = getLabeledBookmarkListEvent(bookmarkListIdentifier)
val deletionEvent = account.signer.sign(DeletionEvent.build(listOf(listEvent))) val deletionEventTemplate = DeletionEvent.build(listOf(listEvent))
val deletionEvent = account.signer.sign(deletionEventTemplate)
account.sendMyPublicAndPrivateOutbox(deletionEvent) account.sendMyPublicAndPrivateOutbox(deletionEvent)
} }
suspend fun addBookmarkToList( suspend fun addBookmarkToList(
bookmark: BookmarkIdTag, bookmark: BookmarkIdTag,
bookmarkList: LabeledBookmarkList, bookmarkListIdentifier: String,
isBookmarkPrivate: Boolean, isBookmarkPrivate: Boolean,
account: Account, account: Account,
) { ) {
val currentBookmarkList = getLabeledBookmarkListEvent(bookmarkList.identifier) val currentBookmarkList = getLabeledBookmarkListEvent(bookmarkListIdentifier)
val updatedList = val updatedList =
LabeledBookmarkListEvent.addBookmark( LabeledBookmarkListEvent.addBookmark(
earlierVersion = currentBookmarkList, earlierVersion = currentBookmarkList,
@@ -231,11 +237,11 @@ class LabeledBookmarkListsState(
suspend fun removeBookmarkFromList( suspend fun removeBookmarkFromList(
bookmark: BookmarkIdTag, bookmark: BookmarkIdTag,
bookmarkList: LabeledBookmarkList, bookmarkListIdentifier: String,
isBookmarkPrivate: Boolean, isBookmarkPrivate: Boolean,
account: Account, account: Account,
) { ) {
val currentBookmarkList = getLabeledBookmarkListEvent(bookmarkList.identifier) val currentBookmarkList = getLabeledBookmarkListEvent(bookmarkListIdentifier)
val updatedList = val updatedList =
LabeledBookmarkListEvent.removeBookmark( LabeledBookmarkListEvent.removeBookmark(
earlierVersion = currentBookmarkList, earlierVersion = currentBookmarkList,
@@ -25,6 +25,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.EventBookmark import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.EventBookmark
@@ -32,11 +33,12 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlin.collections.emptyList
@Stable @Stable
class BookmarkGroupViewModel( class BookmarkGroupViewModel(
val account: Account, val account: Account,
bookmarkGroupIdentifier: String, val bookmarkGroupIdentifier: String,
) : ViewModel() { ) : ViewModel() {
val selectedBookmarkGroupFlow = val selectedBookmarkGroupFlow =
account.labeledBookmarkLists account.labeledBookmarkLists
@@ -46,75 +48,83 @@ class BookmarkGroupViewModel(
fun publicPosts() = fun publicPosts() =
selectedBookmarkGroupFlow selectedBookmarkGroupFlow
.filterNotNull() .filterNotNull()
.map { group -> .map { group -> group.publicPostBookmarks.map { account.cache.getOrCreateNote(it.eventId) } }
group.publicBookmarks .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
.filter { it is EventBookmark }
.map { account.cache.getOrCreateNote((it as EventBookmark).eventId) }
}.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun privatePosts() = fun privatePosts() =
selectedBookmarkGroupFlow selectedBookmarkGroupFlow
.filterNotNull() .filterNotNull()
.map { group -> .map { group -> group.privatePostBookmarks.map { account.cache.getOrCreateNote(it.eventId) } }
group.privateBookmarks .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
.filter { it is EventBookmark }
.map { account.cache.getOrCreateNote((it as EventBookmark).eventId) }
}.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun publicArticles() = fun publicArticles() =
selectedBookmarkGroupFlow selectedBookmarkGroupFlow
.filterNotNull() .filterNotNull()
.map { group -> .map { group -> group.publicArticleBookmarks.map { account.cache.getOrCreateAddressableNote(it.address) } }
group.publicBookmarks .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
.filter { it is AddressBookmark }
.map { account.cache.getOrCreateAddressableNote((it as AddressBookmark).address) }
}.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
fun privateArticles() = fun privateArticles() =
selectedBookmarkGroupFlow selectedBookmarkGroupFlow
.filterNotNull() .filterNotNull()
.map { group -> .map { group -> group.privateArticleBookmarks.map { account.cache.getOrCreateAddressableNote(it.address) } }
group.privateBookmarks .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
.filter { it is AddressBookmark }
.map { account.cache.getOrCreateAddressableNote((it as AddressBookmark).address) }
}.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
// TODO: Add implementations for Hashtag and Link bookmarks // TODO: Add implementations for Hashtag and Link bookmarks
suspend fun deleteBookmarkGroup() { suspend fun deleteBookmarkGroup(groupIdentifier: String) {
selectedBookmarkGroupFlow.value?.let { account.labeledBookmarkLists.deleteBookmarkList(groupIdentifier, account)
account.labeledBookmarkLists.deleteBookmarkList(it, account)
}
} }
suspend fun addBookmarkToGroup( suspend fun addBookmarkToGroup(
groupIdentifier: String = bookmarkGroupIdentifier,
bookmark: BookmarkIdTag, bookmark: BookmarkIdTag,
isPrivate: Boolean, isPrivate: Boolean,
account: Account,
) { ) {
selectedBookmarkGroupFlow.value?.let { account.labeledBookmarkLists.addBookmarkToList(
account.labeledBookmarkLists.addBookmarkToList( bookmark,
bookmark, groupIdentifier,
it, isPrivate,
isPrivate, account,
account, )
) }
}
suspend fun removePostBookmark(
groupIdentifier: String = bookmarkGroupIdentifier,
bookmarkPostId: String,
isPrivate: Boolean,
) {
val eventBookmark = EventBookmark(bookmarkPostId)
removeBookmarkFromGroup(
groupIdentifier,
eventBookmark,
isPrivate,
)
}
suspend fun removeArticleBookmark(
groupIdentifier: String = bookmarkGroupIdentifier,
bookmarkArticleAddress: Address,
isPrivate: Boolean,
) {
val eventBookmark = AddressBookmark(bookmarkArticleAddress)
removeBookmarkFromGroup(
groupIdentifier,
eventBookmark,
isPrivate,
)
} }
suspend fun removeBookmarkFromGroup( suspend fun removeBookmarkFromGroup(
groupIdentifier: String = bookmarkGroupIdentifier,
bookmark: BookmarkIdTag, bookmark: BookmarkIdTag,
isPrivate: Boolean, isPrivate: Boolean,
account: Account,
) { ) {
selectedBookmarkGroupFlow.value?.let { account.labeledBookmarkLists.removeBookmarkFromList(
account.labeledBookmarkLists.removeBookmarkFromList( bookmark,
bookmark, groupIdentifier,
it, isPrivate,
isPrivate, account,
account, )
)
}
} }
class Initializer( class Initializer(