From 194f57acc381972f263e87437f83296f36fb70a2 Mon Sep 17 00:00:00 2001 From: KotlinGeekDev Date: Fri, 28 Nov 2025 04:31:08 +0100 Subject: [PATCH] Support moving articles/posts from private to public and vice versa. --- .../bookmarkgroups/display/ArticleListView.kt | 15 +++++++++ .../display/BookmarkGroupItemOptions.kt | 18 ++++++++--- .../display/BookmarkGroupScreen.kt | 18 +++++++++++ .../display/BookmarkGroupViewModel.kt | 31 +++++++++++++++++-- .../bookmarkgroups/display/PostListView.kt | 15 +++++++++ 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/ArticleListView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/ArticleListView.kt index 11317e928..2280da6c1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/ArticleListView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/ArticleListView.kt @@ -43,6 +43,7 @@ fun RenderArticleList( bookmarkGroupViewModel: BookmarkGroupViewModel, pagerState: PagerState, accountViewModel: AccountViewModel, + moveArticleBookmark: (articleAddress: Address, fromPrivate: Boolean) -> Unit, deleteArticleBookmark: (articleAddress: Address, isPrivate: Boolean) -> Unit, nav: INav, modifier: Modifier = Modifier, @@ -56,6 +57,10 @@ fun RenderArticleList( ArticleList( modifier = Modifier.fillMaxSize(), articles = publicArticles, + isArticleBookmarkPrivate = false, + onMoveBookmarkToPrivate = { articleAddress -> + moveArticleBookmark(articleAddress, false) + }, onDeleteArticleBookmark = { articleAddress -> deleteArticleBookmark(articleAddress, false) }, @@ -66,6 +71,10 @@ fun RenderArticleList( ArticleList( modifier = Modifier.fillMaxSize(), articles = privateArticles, + isArticleBookmarkPrivate = true, + onMoveBookmarkToPublic = { articleAddress -> + moveArticleBookmark(articleAddress, true) + }, onDeleteArticleBookmark = { articleAddress -> deleteArticleBookmark(articleAddress, true) }, @@ -80,6 +89,9 @@ fun RenderArticleList( fun ArticleList( modifier: Modifier = Modifier, articles: List, + isArticleBookmarkPrivate: Boolean, + onMoveBookmarkToPublic: (articleAddress: Address) -> Unit = {}, + onMoveBookmarkToPrivate: (articleAddress: Address) -> Unit = {}, onDeleteArticleBookmark: (Address) -> Unit, accountViewModel: AccountViewModel, nav: INav, @@ -101,6 +113,9 @@ fun ArticleList( moreOptions = { BookmarkGroupItemOptions( baseNote = item, + isBookmarkItemPrivate = isArticleBookmarkPrivate, + onMoveBookmarkToPublic = { onMoveBookmarkToPublic(item.address) }, + onMoveBookmarkToPrivate = { onMoveBookmarkToPrivate(item.address) }, onDeleteBookmarkItem = { onDeleteArticleBookmark(item.address) }, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupItemOptions.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupItemOptions.kt index e734d78d9..82fbf5641 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupItemOptions.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupItemOptions.kt @@ -60,6 +60,9 @@ import kotlinx.coroutines.launch @Composable fun BookmarkGroupItemOptions( baseNote: Note, + isBookmarkItemPrivate: Boolean, + onMoveBookmarkToPublic: () -> Unit, + onMoveBookmarkToPrivate: () -> Unit, onDeleteBookmarkItem: () -> Unit, editState: State>? = null, accountViewModel: AccountViewModel, @@ -76,7 +79,10 @@ fun BookmarkGroupItemOptions( if (popupExpanded.value) { BookmarkGroupItemOptionsMenu( note = baseNote, + isBookmarkItemPrivate = isBookmarkItemPrivate, onDismiss = { popupExpanded.value = false }, + onMoveBookmarkToPublic = onMoveBookmarkToPublic, + onMoveBookmarkToPrivate = onMoveBookmarkToPrivate, onDeleteBookmarkItem = onDeleteBookmarkItem, editState = editState, accountViewModel = accountViewModel, @@ -89,7 +95,10 @@ fun BookmarkGroupItemOptions( @Composable fun BookmarkGroupItemOptionsMenu( note: Note, + isBookmarkItemPrivate: Boolean, onDismiss: () -> Unit, + onMoveBookmarkToPublic: () -> Unit, + onMoveBookmarkToPrivate: () -> Unit, onDeleteBookmarkItem: () -> Unit, editState: State>? = null, accountViewModel: AccountViewModel, @@ -149,6 +158,10 @@ fun BookmarkGroupItemOptionsMenu( } val scope = rememberCoroutineScope() + DropdownMenuItem( + text = { Text(if (isBookmarkItemPrivate) "Move to Public" else "Move to Private") }, + onClick = if (isBookmarkItemPrivate) onMoveBookmarkToPublic else onMoveBookmarkToPrivate, + ) DropdownMenuItem( text = { Text(stringRes(R.string.bookmark_remove_action_label)) }, onClick = { @@ -156,11 +169,6 @@ fun BookmarkGroupItemOptionsMenu( onDismiss() }, ) - // TODO: Work on moving feature below -// DropdownMenuItem( -// text = { Text("Move to Public") }, -// onClick = -// ) HorizontalDivider(thickness = DividerThickness) if (!state.isFollowingAuthor) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupScreen.kt index e06eaea47..e4ca1fc88 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupScreen.kt @@ -162,6 +162,15 @@ fun BookmarkGroupScreenView( bookmarkGroupViewModel, pagerState, accountViewModel, + movePostBookmark = { postId, isPrivate -> + accountViewModel.launchSigner { + bookmarkGroupViewModel.movePostBookmark( + groupIdentifier = bookmarkGroupViewModel.bookmarkGroupIdentifier, + postId = postId, + isCurrentlyPrivate = isPrivate, + ) + } + }, deletePostBookmark = { postId, isPrivate -> accountViewModel.launchSigner { bookmarkGroupViewModel.removePostBookmark( @@ -178,6 +187,15 @@ fun BookmarkGroupScreenView( bookmarkGroupViewModel, pagerState, accountViewModel, + moveArticleBookmark = { articleAddress, isPrivate -> + accountViewModel.launchSigner { + bookmarkGroupViewModel.moveArticleBookmark( + groupIdentifier = bookmarkGroupViewModel.bookmarkGroupIdentifier, + articleAddress = articleAddress, + isCurrentlyPrivate = isPrivate, + ) + } + }, deleteArticleBookmark = { articleAddress, isPrivate -> accountViewModel.launchSigner { bookmarkGroupViewModel.removeArticleBookmark( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupViewModel.kt index a0cd966be..3763d26c6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/BookmarkGroupViewModel.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.AddressBookmark import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.BookmarkIdTag import com.vitorpamplona.quartz.nip51Lists.bookmarkList.tags.EventBookmark +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.map @@ -69,8 +70,6 @@ class BookmarkGroupViewModel( .map { group -> group.privateArticleBookmarks.map { account.cache.getOrCreateAddressableNote(it.address) } } .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList()) - // TODO: Add implementations for Hashtag and Link bookmarks - suspend fun deleteBookmarkGroup(groupIdentifier: String) { account.labeledBookmarkLists.deleteBookmarkList(groupIdentifier, account) } @@ -88,6 +87,34 @@ class BookmarkGroupViewModel( ) } + suspend fun movePostBookmark( + groupIdentifier: String = bookmarkGroupIdentifier, + postId: String, + isCurrentlyPrivate: Boolean, + ) { + val eventBookmark = EventBookmark(postId) + moveBookmark(groupIdentifier, eventBookmark, isCurrentlyPrivate) + } + + suspend fun moveArticleBookmark( + groupIdentifier: String = bookmarkGroupIdentifier, + articleAddress: Address, + isCurrentlyPrivate: Boolean, + ) { + val eventBookmark = AddressBookmark(articleAddress) + moveBookmark(groupIdentifier, eventBookmark, isCurrentlyPrivate) + } + + suspend fun moveBookmark( + groupIdentifier: String = bookmarkGroupIdentifier, + bookmark: BookmarkIdTag, + isCurrentlyPrivate: Boolean, + ) { + removeBookmarkFromGroup(groupIdentifier, bookmark, isCurrentlyPrivate) + delay(1000L) + addBookmarkToGroup(groupIdentifier, bookmark, !isCurrentlyPrivate) + } + suspend fun removePostBookmark( groupIdentifier: String = bookmarkGroupIdentifier, bookmarkPostId: String, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/PostListView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/PostListView.kt index d6976df7e..93562c8ef 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/PostListView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/bookmarkgroups/display/PostListView.kt @@ -42,6 +42,7 @@ fun RenderPostList( bookmarkGroupViewModel: BookmarkGroupViewModel, pagerState: PagerState, accountViewModel: AccountViewModel, + movePostBookmark: (postId: String, fromPrivate: Boolean) -> Unit, deletePostBookmark: (postId: String, isPrivate: Boolean) -> Unit, nav: INav, modifier: Modifier = Modifier, @@ -55,6 +56,10 @@ fun RenderPostList( PostList( modifier = Modifier.fillMaxSize(), posts = publicPosts, + isPostBookmarkPrivate = false, + onMoveBookmarkToPrivate = { postId -> + movePostBookmark(postId, false) + }, onDeletePostBookmark = { postId -> deletePostBookmark(postId, false) }, @@ -65,6 +70,10 @@ fun RenderPostList( PostList( modifier = Modifier.fillMaxSize(), posts = privatePosts, + isPostBookmarkPrivate = true, + onMoveBookmarkToPublic = { postId -> + movePostBookmark(postId, true) + }, onDeletePostBookmark = { postId -> deletePostBookmark(postId, true) }, @@ -79,6 +88,9 @@ fun RenderPostList( private fun PostList( modifier: Modifier = Modifier, posts: List, + isPostBookmarkPrivate: Boolean, + onMoveBookmarkToPublic: (postId: String) -> Unit = {}, + onMoveBookmarkToPrivate: (postId: String) -> Unit = {}, onDeletePostBookmark: (postId: String) -> Unit, accountViewModel: AccountViewModel, nav: INav, @@ -100,6 +112,9 @@ private fun PostList( moreOptions = { BookmarkGroupItemOptions( baseNote = item, + isBookmarkItemPrivate = isPostBookmarkPrivate, + onMoveBookmarkToPublic = { onMoveBookmarkToPublic(item.idHex) }, + onMoveBookmarkToPrivate = { onMoveBookmarkToPrivate(item.idHex) }, onDeleteBookmarkItem = { onDeletePostBookmark(item.idHex) }, accountViewModel = accountViewModel, nav = nav,