From ca17fe1e2228a5be9d476e40c9d2ec1825cb8bb9 Mon Sep 17 00:00:00 2001 From: Erik Cavazos Date: Sun, 27 Aug 2023 23:03:40 -0600 Subject: [PATCH] WIP --- .idea/assetWizardSettings.xml | 4 +- .idea/deploymentTargetDropDown.xml | 4 +- .../java/com/isolaatti/home/FeedFragment.kt | 11 ++-- .../home/presentation/FeedViewModel.kt | 4 +- .../presentation/BottomSheetPostComments.kt | 29 +++++++-- .../options_bottom_sheet/domain/Options.kt | 62 ++++++++++++++----- .../BottomSheetPostOptionsViewModel.kt | 27 +++++--- .../ui/BottomSheetPostOptionsFragment.kt | 1 + .../profile/ui/ProfileMainFragment.kt | 43 +++++++++++++ .../res/drawable/baseline_download_24.xml | 5 ++ .../main/res/drawable/baseline_save_24.xml | 5 ++ .../res/layout/bottom_sheet_post_options.xml | 12 +++- app/src/main/res/values/strings.xml | 3 + build.gradle | 4 +- 14 files changed, 171 insertions(+), 43 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_download_24.xml create mode 100644 app/src/main/res/drawable/baseline_save_24.xml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 3dcf6b5..c841460 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -308,7 +308,7 @@ @@ -318,7 +318,7 @@ diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index f5f7c39..07ae0ed 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -7,11 +7,11 @@ - + - + \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/home/FeedFragment.kt b/app/src/main/java/com/isolaatti/home/FeedFragment.kt index b505ec5..2a85687 100644 --- a/app/src/main/java/com/isolaatti/home/FeedFragment.kt +++ b/app/src/main/java/com/isolaatti/home/FeedFragment.kt @@ -30,6 +30,7 @@ import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked import com.isolaatti.posting.common.options_bottom_sheet.domain.Options import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel import com.isolaatti.posting.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment +import com.isolaatti.posting.posts.domain.entity.Post import com.isolaatti.posting.posts.presentation.CreatePostContract import com.isolaatti.posting.posts.presentation.EditPostContract import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter @@ -80,26 +81,26 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { // region observers - val optionsObserver: Observer = Observer { optionClicked -> + private val optionsObserver: Observer = Observer { optionClicked -> if(optionClicked?.callerId == CALLER_ID) { // post id should come as payload - val postId = optionClicked.payload as? Long ?: return@Observer + val post = optionClicked.payload as? Post ?: return@Observer when(optionClicked.optionId) { Options.Option.OPTION_DELETE -> { Dialogs.buildDeletePostDialog(requireContext()) { delete -> optionsViewModel.handle() if(delete) { - viewModel.deletePost(postId) + viewModel.deletePost(post.id) } }.show() } Options.Option.OPTION_EDIT -> { optionsViewModel.handle() - editDiscussion.launch(postId) + editDiscussion.launch(post.id) } Options.Option.OPTION_REPORT -> { - + optionsViewModel.handle() } } } diff --git a/app/src/main/java/com/isolaatti/home/presentation/FeedViewModel.kt b/app/src/main/java/com/isolaatti/home/presentation/FeedViewModel.kt index b3457ba..c6a938f 100644 --- a/app/src/main/java/com/isolaatti/home/presentation/FeedViewModel.kt +++ b/app/src/main/java/com/isolaatti/home/presentation/FeedViewModel.kt @@ -33,11 +33,12 @@ class FeedViewModel @Inject constructor( postsRepository.getFeed(getLastId()).onEach { listResource -> when (listResource) { is Resource.Success -> { + val eventType = if((postsList?.size ?: 0) > 0) UpdateEvent.UpdateType.PAGE_ADDED else UpdateEvent.UpdateType.REFRESH loadingPosts.postValue(false) posts.postValue(Pair(postsList?.apply { addAll(listResource.data ?: listOf()) } ?: listResource.data, - UpdateEvent(UpdateEvent.UpdateType.PAGE_ADDED, null))) + UpdateEvent(eventType, null))) noMoreContent.postValue(listResource.data?.size == 0) } @@ -50,6 +51,7 @@ class FeedViewModel @Inject constructor( is Resource.Error -> { //errorLoading.postValue(feedDtoResource.errorType) } + } isLoadingFromScrolling = false }.flowOn(Dispatchers.IO).launchIn(this) diff --git a/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt b/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt index cb5fade..fcdd7af 100644 --- a/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt +++ b/app/src/main/java/com/isolaatti/posting/comments/presentation/BottomSheetPostComments.kt @@ -11,13 +11,17 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.isolaatti.common.Dialogs import com.isolaatti.databinding.BottomSheetPostCommentsBinding +import com.isolaatti.home.FeedFragment +import com.isolaatti.posting.comments.domain.model.Comment import com.isolaatti.posting.common.domain.OnUserInteractedCallback import com.isolaatti.posting.common.domain.Ownable import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked import com.isolaatti.posting.common.options_bottom_sheet.domain.Options import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel import com.isolaatti.posting.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment +import com.isolaatti.posting.posts.domain.entity.Post import com.isolaatti.profile.ui.ProfileActivity import com.isolaatti.utils.PicassoImagesPluginDef import dagger.hilt.android.AndroidEntryPoint @@ -36,9 +40,27 @@ class BottomSheetPostComments() : BottomSheetDialogFragment(), OnUserInteractedC val optionsViewModel: BottomSheetPostOptionsViewModel by activityViewModels() - val optionsObserver: Observer = Observer { - if(it?.callerId == CALLER_ID) { - optionsViewModel.optionClicked(-1) + val optionsObserver: Observer = Observer { optionClicked -> + if(optionClicked?.callerId == BottomSheetPostComments.CALLER_ID) { + val comment = optionClicked.payload as? Comment ?: return@Observer + when(optionClicked.optionId) { + Options.Option.OPTION_DELETE -> { + Dialogs.buildDeletePostDialog(requireContext()) { delete -> + optionsViewModel.handle() + if(delete) { + // remove comment + } + }.show() + + } + Options.Option.OPTION_EDIT -> { + optionsViewModel.handle() + //editDiscussion.launch(post.id) + } + Options.Option.OPTION_REPORT -> { + optionsViewModel.handle() + } + } } } @@ -95,7 +117,6 @@ class BottomSheetPostComments() : BottomSheetDialogFragment(), OnUserInteractedC } - optionsViewModel.optionClicked(-1) optionsViewModel.optionClicked.observe(viewLifecycleOwner, optionsObserver) } diff --git a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt index 04e6a5c..eceff89 100644 --- a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt +++ b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/domain/Options.kt @@ -17,31 +17,61 @@ data class Options( const val OPTION_DELETE = 1 const val OPTION_EDIT = 2 const val OPTION_REPORT = 3 + const val OPTION_SAVE = 4 + const val OPTION_SNAPSHOT = 5 } } companion object { const val POST_OPTIONS = 1 + const val COMMENT_OPTIONS = 2 val noOptions = Options(0, listOf()) - val myPostOptions = Options(R.string.post_options_title, listOf( - Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), - Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT), - Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) - )) - val postOptions = Options(R.string.post_options_title, listOf( - Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) - )) + fun getPostsOptions(userOwned: Boolean, savable: Boolean, snapshotAble: Boolean): Options { + val list = mutableListOf( + Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) + ) - val myCommentOptions = Options(R.string.post_options_title, listOf( - Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), - Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT), - Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) - )) + if(userOwned) { + list.addAll(listOf( + Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), + Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT)) + ) + } - val commentOptions = Options(R.string.post_options_title, listOf( - Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) - )) + if(savable) { + list.add(Option(R.string.save, R.drawable.baseline_save_24, Option.OPTION_SAVE)) + } + + if(snapshotAble) { + list.add(Option(R.string.save_snapshot, R.drawable.baseline_download_24, Option.OPTION_SNAPSHOT)) + } + + return Options(R.string.post_options_title, list) + } + + fun getCommentOptions(userOwned: Boolean, savable: Boolean, snapshotAble: Boolean): Options { + val list = mutableListOf( + Option(R.string.report, R.drawable.baseline_report_24, Option.OPTION_REPORT) + ) + + if(userOwned) { + list.addAll(listOf( + Option(R.string.delete, R.drawable.baseline_delete_24, Option.OPTION_DELETE), + Option(R.string.edit, R.drawable.baseline_edit_24, Option.OPTION_EDIT)) + ) + } + + if(savable) { + list.add(Option(R.string.save, R.drawable.baseline_save_24, Option.OPTION_SAVE)) + } + + if(snapshotAble) { + list.add(Option(R.string.save_snapshot, R.drawable.baseline_download_24, Option.OPTION_SNAPSHOT)) + } + + return Options(R.string.comment_options, list) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/presentation/BottomSheetPostOptionsViewModel.kt b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/presentation/BottomSheetPostOptionsViewModel.kt index ce3acc5..2c389ec 100644 --- a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/presentation/BottomSheetPostOptionsViewModel.kt +++ b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/presentation/BottomSheetPostOptionsViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope import com.isolaatti.posting.common.domain.Ownable import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked import com.isolaatti.posting.common.options_bottom_sheet.domain.Options +import com.isolaatti.posting.common.options_bottom_sheet.domain.Options.Companion.COMMENT_OPTIONS import com.isolaatti.posting.common.options_bottom_sheet.domain.Options.Companion.POST_OPTIONS import com.isolaatti.posting.posts.data.remote.FeedDto import com.isolaatti.settings.domain.UserIdSetting @@ -38,27 +39,33 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett when(options) { POST_OPTIONS -> { userIdSetting.getUserId()?.let { userId -> - if(userId == payload?.userId) { - _options.postValue(Options.myPostOptions) - } else { - _options.postValue(Options.postOptions) - } + _options.postValue(Options.getPostsOptions( + userOwned = userId == payload?.userId, + savable = false, + snapshotAble = false) + ) + _callerId = callerId + _payload = payload + } + } + COMMENT_OPTIONS -> { + userIdSetting.getUserId()?.let { userId -> + _options.postValue(Options.getCommentOptions( + userOwned = userId == payload?.userId, + savable = false, + snapshotAble = false) + ) _callerId = callerId _payload = payload } - } } } } - - - } fun optionClicked(optionId: Int) { _optionClicked.postValue(OptionClicked(optionId, _callerId, _payload)) } - } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/ui/BottomSheetPostOptionsFragment.kt b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/ui/BottomSheetPostOptionsFragment.kt index 8893551..ac5a31e 100644 --- a/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/ui/BottomSheetPostOptionsFragment.kt +++ b/app/src/main/java/com/isolaatti/posting/common/options_bottom_sheet/ui/BottomSheetPostOptionsFragment.kt @@ -55,6 +55,7 @@ class BottomSheetPostOptionsFragment : BottomSheetDialogFragment(), OptionsRecyc private fun renderOptions(options: Options) { + viewBinding.title.text = requireContext().getText(options.title) viewBinding.recyclerOptions.adapter = OptionsRecyclerAdapter(options.items, this) viewBinding.recyclerOptions.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) } diff --git a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt index 1b41ea1..9805d3c 100644 --- a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt +++ b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels @@ -13,17 +14,21 @@ import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import com.isolaatti.BuildConfig import com.isolaatti.R +import com.isolaatti.common.Dialogs import com.isolaatti.databinding.FragmentDiscussionsBinding import com.isolaatti.followers.domain.FollowingState import com.isolaatti.home.FeedFragment import com.isolaatti.posting.PostViewerActivity import com.isolaatti.posting.comments.presentation.BottomSheetPostComments import com.isolaatti.posting.common.domain.Ownable +import com.isolaatti.posting.common.options_bottom_sheet.domain.OptionClicked import com.isolaatti.posting.common.options_bottom_sheet.domain.Options import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel import com.isolaatti.posting.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment import com.isolaatti.posting.posts.data.remote.FeedDto import com.isolaatti.posting.posts.domain.entity.Post +import com.isolaatti.posting.posts.presentation.CreatePostContract +import com.isolaatti.posting.posts.presentation.EditPostContract import com.isolaatti.posting.posts.presentation.PostListingRecyclerViewAdapterWiring import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter import com.isolaatti.posting.posts.presentation.UpdateEvent @@ -53,6 +58,18 @@ class ProfileMainFragment : Fragment() { private var scrollRange = -1 private var isShow = false + private val createDiscussion = registerForActivityResult(CreatePostContract()) { + if(it != null) { + Toast.makeText(requireContext(), R.string.posted_successfully, Toast.LENGTH_SHORT).show() + } + } + + private val editDiscussion = registerForActivityResult(EditPostContract()) { + if(it != null) { + viewModel.onPostUpdate(it) + } + } + private val profileObserver = Observer { profile -> Picasso.get() .load(UrlGen.userProfileImage(profile.id)) @@ -102,6 +119,31 @@ class ProfileMainFragment : Fragment() { } } + private val optionsObserver: Observer = Observer { optionClicked -> + if(optionClicked?.callerId == FeedFragment.CALLER_ID) { + // post id should come as payload + val post = optionClicked.payload as? Post ?: return@Observer + when(optionClicked.optionId) { + Options.Option.OPTION_DELETE -> { + Dialogs.buildDeletePostDialog(requireContext()) { delete -> + optionsViewModel.handle() + if(delete) { + viewModel.deletePost(post.id) + } + }.show() + + } + Options.Option.OPTION_EDIT -> { + optionsViewModel.handle() + editDiscussion.launch(post.id) + } + Options.Option.OPTION_REPORT -> { + optionsViewModel.handle() + } + } + } + } + private lateinit var postListingRecyclerViewAdapterWiring: PostListingRecyclerViewAdapterWiring @@ -159,6 +201,7 @@ class ProfileMainFragment : Fragment() { viewModel.profile.observe(viewLifecycleOwner, profileObserver) viewModel.posts.observe(viewLifecycleOwner, postsObserver) viewModel.followingState.observe(viewLifecycleOwner, followingStateObserver) + optionsViewModel.optionClicked.observe(viewLifecycleOwner, optionsObserver) viewModel.loadingPosts.observe(viewLifecycleOwner) { viewBinding.loadingIndicator.visibility = if(it) View.VISIBLE else View.GONE if(!it) { diff --git a/app/src/main/res/drawable/baseline_download_24.xml b/app/src/main/res/drawable/baseline_download_24.xml new file mode 100644 index 0000000..1fc8106 --- /dev/null +++ b/app/src/main/res/drawable/baseline_download_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_save_24.xml b/app/src/main/res/drawable/baseline_save_24.xml new file mode 100644 index 0000000..82070aa --- /dev/null +++ b/app/src/main/res/drawable/baseline_save_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/bottom_sheet_post_options.xml b/app/src/main/res/layout/bottom_sheet_post_options.xml index 3337252..1645ae9 100644 --- a/app/src/main/res/layout/bottom_sheet_post_options.xml +++ b/app/src/main/res/layout/bottom_sheet_post_options.xml @@ -1,5 +1,6 @@ - + + Home Notifications Search + Comment options Record audio @@ -68,4 +69,6 @@ This discussion and all related content will be dropped. Continue? Yes, delete Cancel + Save + Save snapshot \ No newline at end of file diff --git a/build.gradle b/build.gradle index 473dd7e..85111fd 100644 --- a/build.gradle +++ b/build.gradle @@ -12,8 +12,8 @@ buildscript { } } plugins { - id 'com.android.application' version '8.1.0' apply false - id 'com.android.library' version '8.1.0' apply false + id 'com.android.application' version '8.1.1' apply false + id 'com.android.library' version '8.1.1' apply false id 'org.jetbrains.kotlin.android' version '1.8.0' apply false id 'com.google.dagger.hilt.android' version '2.47' apply false } \ No newline at end of file