From 5d032fd583fa081badd22cf06de2a8a82d52ad5c Mon Sep 17 00:00:00 2001 From: Diego Beraldin Date: Thu, 9 Nov 2023 19:40:27 +0100 Subject: [PATCH] feat: cross-post (#117) * feat: cross-post * refactor: id-based options * fix: show actions only for logged users --- .../raccoonforlemmy/core/commonui/di/Utils.kt | 10 +- .../communitydetail/CommunityDetailScreen.kt | 158 ++++++++++++----- .../components/CollapsedCommentCard.kt | 4 +- .../core/commonui/components/CommentCard.kt | 4 +- .../commonui/components/CommunityHeader.kt | 10 +- .../core/commonui/components/CommunityItem.kt | 5 +- .../commonui/components/MultiCommunityItem.kt | 4 +- .../core/commonui/components/Options.kt | 20 +++ .../core/commonui/components/PostCard.kt | 12 +- .../commonui/components/PostCardFooter.kt | 10 +- .../core/commonui/components/UserHeader.kt | 10 +- .../createcomment/CreateCommentScreen.kt | 16 +- .../commonui/createpost/CreatePostMviModel.kt | 5 + .../commonui/createpost/CreatePostScreen.kt | 167 ++++++++++++++---- .../createpost/CreatePostViewModel.kt | 38 +++- .../core/commonui/di/CommonUiModule.kt | 14 +- .../raccoonforlemmy/core/commonui/di/Utils.kt | 6 +- .../commonui/postdetail/PostDetailScreen.kt | 143 ++++++++++++--- .../commonui/saveditems/SavedItemsScreen.kt | 51 ++++-- .../CommunityItemPlaceholder.kt | 57 ++++++ .../selectcommunity/SelectCommunityDialog.kt | 159 +++++++++++++++++ .../SelectCommunityMviModel.kt | 22 +++ .../SelectCommunityViewModel.kt | 82 +++++++++ .../commonui/userdetail/UserDetailMviModel.kt | 1 + .../commonui/userdetail/UserDetailScreen.kt | 92 ++++++++-- .../userdetail/UserDetailViewModel.kt | 5 + .../raccoonforlemmy/core/commonui/di/Utils.kt | 12 +- .../NotificationCenterContractKeys.kt | 1 + .../feature/home/postlist/PostListScreen.kt | 105 ++++++++--- .../feature/home/postlist/PostsTopBar.kt | 4 +- .../feature/inbox/messages/ChatCard.kt | 3 +- .../profile/logged/ProfileLoggedScreen.kt | 77 ++++++-- .../feature/search/di/ExploreModule.kt | 1 + .../feature/search/main/ExploreTopBar.kt | 4 +- .../detail/MultiCommunityMviModel.kt | 1 + .../detail/MultiCommunityScreen.kt | 37 +++- .../detail/MultiCommunityViewModel.kt | 7 + .../settings/ui/components/SettingsHeader.kt | 4 +- .../commonMain/resources/MR/base/strings.xml | 6 +- .../commonMain/resources/MR/de/strings.xml | 6 +- .../commonMain/resources/MR/el/strings.xml | 12 +- .../commonMain/resources/MR/es/strings.xml | 6 +- .../commonMain/resources/MR/fr/strings.xml | 6 +- .../commonMain/resources/MR/it/strings.xml | 6 +- .../commonMain/resources/MR/nl/strings.xml | 18 +- .../commonMain/resources/MR/pt/strings.xml | 6 +- .../commonMain/resources/MR/ro/strings.xml | 8 +- 47 files changed, 1172 insertions(+), 263 deletions(-) create mode 100644 core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/Options.kt create mode 100644 core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/selectcommunity/CommunityItemPlaceholder.kt create mode 100644 core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/selectcommunity/SelectCommunityDialog.kt create mode 100644 core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/selectcommunity/SelectCommunityMviModel.kt create mode 100644 core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/selectcommunity/SelectCommunityViewModel.kt diff --git a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt index a5b082778..fdd6dd504 100644 --- a/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt +++ b/core-commonui/src/androidMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/di/Utils.kt @@ -20,6 +20,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.Navigat import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailMviModel import com.github.diegoberaldin.raccoonforlemmy.core.commonui.report.CreateReportMviModel import com.github.diegoberaldin.raccoonforlemmy.core.commonui.saveditems.SavedItemsMviModel +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.selectcommunity.SelectCommunityMviModel import com.github.diegoberaldin.raccoonforlemmy.core.commonui.userdetail.UserDetailMviModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel @@ -108,9 +109,9 @@ actual fun getCreateCommentViewModel( return res } -actual fun getCreatePostViewModel(communityId: Int?, editedPostId: Int?): CreatePostMviModel { +actual fun getCreatePostViewModel(editedPostId: Int?): CreatePostMviModel { val res: CreatePostMviModel by inject(clazz = CreatePostMviModel::class.java, - parameters = { parametersOf(communityId, editedPostId) }) + parameters = { parametersOf(editedPostId) }) return res } @@ -151,6 +152,11 @@ actual fun getCreateReportViewModel( return res } +actual fun getSelectCommunityViewModel(): SelectCommunityMviModel { + val res: SelectCommunityMviModel by inject(SelectCommunityMviModel::class.java) + return res +} + @Composable actual fun getCustomTextToolbar( diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt index b3446eae5..db7e462f7 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/communitydetail/CommunityDetailScreen.kt @@ -72,6 +72,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.Comm import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityHeader import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenu import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenuItem +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option +import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.OptionId import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.ProgressHud @@ -321,16 +323,18 @@ class CommunityDetailScreen( } }, ) - this += FloatingActionButtonMenuItem( - icon = Icons.Default.ClearAll, - text = stringResource(MR.strings.action_clear_read), - onSelected = rememberCallback { - model.reduce(CommunityDetailMviModel.Intent.ClearRead) - scope.launch { - lazyListState.scrollToItem(0) - } - }, - ) + if (uiState.currentUserId != null) { + this += FloatingActionButtonMenuItem( + icon = Icons.Default.ClearAll, + text = stringResource(MR.strings.action_clear_read), + onSelected = rememberCallback { + model.reduce(CommunityDetailMviModel.Intent.ClearRead) + scope.launch { + lazyListState.scrollToItem(0) + } + }, + ) + } if (!isOnOtherInstance) { this += FloatingActionButtonMenuItem( icon = Icons.Default.Create, @@ -378,21 +382,36 @@ class CommunityDetailScreen( community = uiState.community, autoLoadImages = uiState.autoLoadImages, options = listOf( - stringResource(MR.strings.community_detail_info), - stringResource(MR.strings.community_detail_instance_info), - stringResource(MR.strings.community_detail_block), - stringResource(MR.strings.community_detail_block_instance), + Option( + OptionId.Info, + stringResource(MR.strings.community_detail_info) + ), + Option( + OptionId.InfoInstance, + stringResource(MR.strings.community_detail_instance_info) + ), + Option( + OptionId.Block, + stringResource(MR.strings.community_detail_block) + ), + Option( + OptionId.BlockInstance, + stringResource(MR.strings.community_detail_block_instance) + ), ), onOpenImage = rememberCallbackArgs { url -> navigationCoordinator.getRootNavigator() ?.push(ZoomableImageScreen(url)) }, - onOptionSelected = rememberCallbackArgs { optionIdx -> - when (optionIdx) { - 3 -> model.reduce(CommunityDetailMviModel.Intent.BlockInstance) - 2 -> model.reduce(CommunityDetailMviModel.Intent.Block) + onOptionSelected = rememberCallbackArgs { optionId -> + when (optionId) { + OptionId.BlockInstance -> model.reduce( + CommunityDetailMviModel.Intent.BlockInstance + ) - 1 -> { + OptionId.Block -> model.reduce(CommunityDetailMviModel.Intent.Block) + + OptionId.InfoInstance -> { navigationCoordinator.getRootNavigator()?.push( InstanceInfoScreen( url = uiState.community.instanceUrl, @@ -400,11 +419,13 @@ class CommunityDetailScreen( ) } - else -> { + OptionId.Info -> { navigationCoordinator.getBottomNavigator()?.show( CommunityInfoScreen(uiState.community), ) } + + else -> Unit } }, ) @@ -544,54 +565,95 @@ class CommunityDetailScreen( ) }, options = buildList { - add(stringResource(MR.strings.post_action_share)) - add(stringResource(MR.strings.post_action_hide)) - add(stringResource(MR.strings.post_action_see_raw)) - add(stringResource(MR.strings.post_action_report)) - if (post.creator?.id == uiState.currentUserId && !isOnOtherInstance) { - add(stringResource(MR.strings.post_action_edit)) - add(stringResource(MR.strings.comment_action_delete)) - } - }, - onOptionSelected = rememberCallbackArgs(model) { optionIdx -> - when (optionIdx) { - 5 -> model.reduce( - CommunityDetailMviModel.Intent.DeletePost( - post.id + add( + Option( + OptionId.Share, + stringResource(MR.strings.post_action_share) + ) + ) + if (uiState.currentUserId != null) { + add( + Option( + OptionId.Hide, + stringResource(MR.strings.post_action_hide) ) ) + } + add( + Option( + OptionId.SeeRaw, + stringResource(MR.strings.post_action_see_raw) + ) + ) + if (uiState.currentUserId != null) { + add( + Option( + OptionId.CrossPost, + stringResource(MR.strings.post_action_cross_post) + ) + ) + add( + Option( + OptionId.Report, + stringResource(MR.strings.post_action_report) + ) + ) + } + if (post.creator?.id == uiState.currentUserId && !isOnOtherInstance) { + add( + Option( + OptionId.Edit, + stringResource(MR.strings.post_action_edit) + ) + ) + add( + Option( + OptionId.Delete, + stringResource(MR.strings.comment_action_delete) + ) + ) + } + }, + onOptionSelected = rememberCallbackArgs(model) { optionId -> + when (optionId) { + OptionId.Delete -> model.reduce( + CommunityDetailMviModel.Intent.DeletePost(post.id) + ) - 4 -> { + OptionId.Edit -> { navigationCoordinator.getBottomNavigator() ?.show( - CreatePostScreen( - editedPost = post, - ) + CreatePostScreen(editedPost = post) ) } - 3 -> { + OptionId.Report -> { navigationCoordinator.getBottomNavigator() ?.show( - CreateReportScreen( - postId = post.id - ) + CreateReportScreen(postId = post.id) ) } - 2 -> { + OptionId.CrossPost -> { + navigationCoordinator.getBottomNavigator() + ?.show( + CreatePostScreen(crossPost = post) + ) + } + + OptionId.SeeRaw -> { rawContent = post } - 1 -> model.reduce( - CommunityDetailMviModel.Intent.Hide( - post.id - ) + OptionId.Hide -> model.reduce( + CommunityDetailMviModel.Intent.Hide(post.id) ) - else -> model.reduce( + OptionId.Share -> model.reduce( CommunityDetailMviModel.Intent.SharePost(post.id) ) + + else -> Unit } }) }, diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt index 2fb2c7c11..bb7f8b3ba 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt @@ -31,13 +31,13 @@ fun CollapsedCommentCard( modifier: Modifier = Modifier, separateUpAndDownVotes: Boolean = false, autoLoadImages: Boolean = true, - options: List = emptyList(), + options: List