From f91fa2d27d014389cbc2363b589cf00486fb91a9 Mon Sep 17 00:00:00 2001 From: erike Date: Fri, 25 Aug 2023 00:18:32 -0600 Subject: [PATCH] WIP 2 --- .../main/java/com/isolaatti/common/Dialogs.kt | 1 + .../java/com/isolaatti/home/FeedFragment.kt | 33 +++++++++++++++---- .../posting/posts/data/remote/EditPostDto.kt | 4 +-- .../posting/posts/data/remote/PostApi.kt | 5 +++ .../data/repository/PostsRepositoryImpl.kt | 19 +++++++++++ .../posting/posts/domain/PostsRepository.kt | 1 + .../posts/domain/use_case/LoadSinglePost.kt | 13 ++++++++ .../posts/presentation/CreatePostContract.kt | 21 ++++++++++++ .../posts/presentation/CreatePostViewModel.kt | 17 +++++++++- .../posts/presentation/EditPostContract.kt | 25 ++++++++++++++ .../presentation/PostListingViewModelBase.kt | 4 +++ .../posting/posts/ui/CreatePostActivity.kt | 20 +++++------ 12 files changed, 141 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/isolaatti/posting/posts/domain/use_case/LoadSinglePost.kt create mode 100644 app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostContract.kt create mode 100644 app/src/main/java/com/isolaatti/posting/posts/presentation/EditPostContract.kt diff --git a/app/src/main/java/com/isolaatti/common/Dialogs.kt b/app/src/main/java/com/isolaatti/common/Dialogs.kt index c1f5424..c0f8817 100644 --- a/app/src/main/java/com/isolaatti/common/Dialogs.kt +++ b/app/src/main/java/com/isolaatti/common/Dialogs.kt @@ -11,5 +11,6 @@ object Dialogs { .setMessage(R.string.post_will_dropped) .setPositiveButton(R.string.yes_continue) {_, _ -> onContinue(true)} .setNegativeButton(R.string.cancel) { _, _ -> onContinue(false)} + .setOnCancelListener { onContinue(false) } } } \ 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 a529d75..be1eeef 100644 --- a/app/src/main/java/com/isolaatti/home/FeedFragment.kt +++ b/app/src/main/java/com/isolaatti/home/FeedFragment.kt @@ -1,6 +1,5 @@ package com.isolaatti.home -import android.app.Activity import android.content.Intent import android.os.Bundle import androidx.fragment.app.Fragment @@ -10,7 +9,6 @@ import android.view.ViewGroup import android.widget.ImageView import android.widget.TextView import android.widget.Toast -import androidx.activity.result.contract.ActivityResultContracts import androidx.constraintlayout.widget.ConstraintLayout import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer @@ -31,8 +29,9 @@ 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.presentation.CreatePostContract +import com.isolaatti.posting.posts.presentation.EditPostContract import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter -import com.isolaatti.posting.posts.ui.CreatePostActivity import com.isolaatti.profile.ui.ProfileActivity import com.isolaatti.settings.ui.SettingsActivity import com.isolaatti.utils.PicassoImagesPluginDef @@ -62,12 +61,24 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { private lateinit var viewBinding: FragmentFeedBinding private lateinit var adapter: PostsRecyclerViewAdapter - private val createDiscussion = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - if(it.resultCode == Activity.RESULT_OK) { + // region launchers + + 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) + } + } + + // endregion + + // region observers + val optionsObserver: Observer = Observer { optionClicked -> if(optionClicked?.callerId == CALLER_ID) { // post id should come as payload @@ -84,7 +95,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { } Options.Option.OPTION_EDIT -> { optionsViewModel.handle() - CreatePostActivity.startActivityEditMode(requireContext(), postId) + editDiscussion.launch(postId) } Options.Option.OPTION_REPORT -> { @@ -93,6 +104,9 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { } } + // endregion + + // region lifecycle override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? @@ -102,6 +116,9 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { return viewBinding.root } + // endregion + + // region events override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) viewBinding.topAppBar.setNavigationOnClickListener { @@ -156,7 +173,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { viewBinding.topAppBar.setOnMenuItemClickListener { when(it.itemId) { R.id.menu_item_new_discussion -> { - createDiscussion.launch(Intent(requireContext(),CreatePostActivity::class.java)) + createDiscussion.launch(Unit) true } else -> { @@ -232,4 +249,6 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback { override fun onLoadMore() { viewModel.getFeed(false) } + + // endregion } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/data/remote/EditPostDto.kt b/app/src/main/java/com/isolaatti/posting/posts/data/remote/EditPostDto.kt index daf4832..8775a47 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/data/remote/EditPostDto.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/data/remote/EditPostDto.kt @@ -3,8 +3,8 @@ package com.isolaatti.posting.posts.data.remote data class EditPostDto( val privacy: Int, val content: String, - val audioId: String?, - val squadId: String?, + val audioId: String? = null, + val squadId: String? = null, val postId: Long ) { companion object { diff --git a/app/src/main/java/com/isolaatti/posting/posts/data/remote/PostApi.kt b/app/src/main/java/com/isolaatti/posting/posts/data/remote/PostApi.kt index 29296f6..e3672f6 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/data/remote/PostApi.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/data/remote/PostApi.kt @@ -2,7 +2,9 @@ package com.isolaatti.posting.posts.data.remote import retrofit2.Call import retrofit2.http.Body +import retrofit2.http.GET import retrofit2.http.POST +import retrofit2.http.Path interface PostApi { @POST("Posting/Make") @@ -14,4 +16,7 @@ interface PostApi { @POST("Posting/Delete") fun deletePost(@Body postToDelete: DeletePostDto): Call + @GET("Fetch/Post/{postId}") + fun getPost(@Path("postId") postId: Long): Call + } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/data/repository/PostsRepositoryImpl.kt b/app/src/main/java/com/isolaatti/posting/posts/data/repository/PostsRepositoryImpl.kt index c9f7b84..956ca92 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/data/repository/PostsRepositoryImpl.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/data/repository/PostsRepositoryImpl.kt @@ -111,4 +111,23 @@ class PostsRepositoryImpl @Inject constructor(private val feedsApi: FeedsApi, pr emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) } } + + override fun loadPost(postId: Long): Flow> = flow { + emit(Resource.Loading()) + try { + val result = postApi.getPost(postId).execute() + if(result.isSuccessful) { + emit(Resource.Success(result.body())) + return@flow + } + when(result.code()) { + 401 -> emit(Resource.Error(Resource.Error.ErrorType.AuthError)) + 404 -> emit(Resource.Error(Resource.Error.ErrorType.NotFoundError)) + 500 -> emit(Resource.Error(Resource.Error.ErrorType.ServerError)) + else -> emit(Resource.Error(Resource.Error.ErrorType.OtherError)) + } + } catch(_: Exception) { + emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/domain/PostsRepository.kt b/app/src/main/java/com/isolaatti/posting/posts/domain/PostsRepository.kt index 2c182ac..22ed597 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/domain/PostsRepository.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/domain/PostsRepository.kt @@ -17,4 +17,5 @@ interface PostsRepository { fun makePost(createPostDto: CreatePostDto): Flow> fun editPost(editPostDto: EditPostDto): Flow> fun deletePost(postId: Long): Flow> + fun loadPost(postId: Long): Flow> } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/domain/use_case/LoadSinglePost.kt b/app/src/main/java/com/isolaatti/posting/posts/domain/use_case/LoadSinglePost.kt new file mode 100644 index 0000000..09d130e --- /dev/null +++ b/app/src/main/java/com/isolaatti/posting/posts/domain/use_case/LoadSinglePost.kt @@ -0,0 +1,13 @@ +package com.isolaatti.posting.posts.domain.use_case + +import com.isolaatti.posting.posts.data.remote.FeedDto +import com.isolaatti.posting.posts.domain.PostsRepository +import com.isolaatti.utils.Resource +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class LoadSinglePost @Inject constructor(private val postsRepository: PostsRepository) { + operator fun invoke(postId: Long): Flow> { + return postsRepository.loadPost(postId) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostContract.kt b/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostContract.kt new file mode 100644 index 0000000..c8ad371 --- /dev/null +++ b/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostContract.kt @@ -0,0 +1,21 @@ +package com.isolaatti.posting.posts.presentation + +import android.app.Activity.RESULT_OK +import android.content.Context +import android.content.Intent +import androidx.activity.result.contract.ActivityResultContract +import com.isolaatti.posting.posts.data.remote.FeedDto +import com.isolaatti.posting.posts.ui.CreatePostActivity +class CreatePostContract : ActivityResultContract() { + override fun createIntent(context: Context, input: Unit): Intent { + return Intent(context, CreatePostActivity::class.java) + } + + override fun parseResult(resultCode: Int, intent: Intent?): FeedDto.PostDto? { + return if(resultCode == RESULT_OK) { + intent?.extras?.getParcelable(CreatePostActivity.EXTRA_KEY_POST_POSTED) + } else { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostViewModel.kt b/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostViewModel.kt index e48dccb..9e49a33 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostViewModel.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/presentation/CreatePostViewModel.kt @@ -5,8 +5,10 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.isolaatti.posting.posts.data.remote.CreatePostDto import com.isolaatti.posting.posts.data.remote.EditPostDto +import com.isolaatti.posting.posts.data.remote.EditPostDto.Companion.PRIVACY_ISOLAATTI import com.isolaatti.posting.posts.data.remote.FeedDto import com.isolaatti.posting.posts.domain.use_case.EditPost +import com.isolaatti.posting.posts.domain.use_case.LoadSinglePost import com.isolaatti.posting.posts.domain.use_case.MakePost import com.isolaatti.utils.Resource import dagger.hilt.android.lifecycle.HiltViewModel @@ -18,11 +20,12 @@ import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class CreatePostViewModel @Inject constructor(private val makePost: MakePost, private val editPost: EditPost) : ViewModel() { +class CreatePostViewModel @Inject constructor(private val makePost: MakePost, private val editPost: EditPost, private val loadPost: LoadSinglePost) : ViewModel() { val validation: MutableLiveData = MutableLiveData(false) val posted: MutableLiveData = MutableLiveData() val error: MutableLiveData = MutableLiveData() val loading: MutableLiveData = MutableLiveData(false) + val postToEdit: MutableLiveData = MutableLiveData() fun postDiscussion(content: String) { viewModelScope.launch { @@ -64,4 +67,16 @@ class CreatePostViewModel @Inject constructor(private val makePost: MakePost, pr } } + fun loadDiscussion(postId: Long) { + viewModelScope.launch { + loadPost(postId).onEach { postRes -> + if(postRes is Resource.Success) { + postRes.data?.let { + postToEdit.postValue(EditPostDto(PRIVACY_ISOLAATTI, content = it.post.textContent, postId = it.post.id)) + } + } + }.flowOn(Dispatchers.IO).launchIn(this) + } + } + } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/presentation/EditPostContract.kt b/app/src/main/java/com/isolaatti/posting/posts/presentation/EditPostContract.kt new file mode 100644 index 0000000..8976c72 --- /dev/null +++ b/app/src/main/java/com/isolaatti/posting/posts/presentation/EditPostContract.kt @@ -0,0 +1,25 @@ +package com.isolaatti.posting.posts.presentation + +import android.app.Activity +import android.content.Context +import android.content.Intent +import androidx.activity.result.contract.ActivityResultContract +import com.isolaatti.posting.posts.data.remote.FeedDto +import com.isolaatti.posting.posts.ui.CreatePostActivity + +class EditPostContract : ActivityResultContract() { + override fun createIntent(context: Context, input: Long): Intent { + return Intent(context, CreatePostActivity::class.java).apply { + putExtra(CreatePostActivity.EXTRA_KEY_MODE, CreatePostActivity.EXTRA_MODE_EDIT) + putExtra(CreatePostActivity.EXTRA_KEY_POST_ID, input) + } + } + + override fun parseResult(resultCode: Int, intent: Intent?): FeedDto.PostDto? { + return if(resultCode == Activity.RESULT_OK) { + intent?.extras?.getParcelable(CreatePostActivity.EXTRA_KEY_POST_POSTED) + } else { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/presentation/PostListingViewModelBase.kt b/app/src/main/java/com/isolaatti/posting/posts/presentation/PostListingViewModelBase.kt index 9e90757..5594372 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/presentation/PostListingViewModelBase.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/presentation/PostListingViewModelBase.kt @@ -93,4 +93,8 @@ abstract class PostListingViewModelBase : ViewModel() { }.flowOn(Dispatchers.IO).launchIn(this) } } + + fun onPostUpdate(post: FeedDto.PostDto) { + + } } \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/posting/posts/ui/CreatePostActivity.kt b/app/src/main/java/com/isolaatti/posting/posts/ui/CreatePostActivity.kt index 0060b43..6c313ba 100644 --- a/app/src/main/java/com/isolaatti/posting/posts/ui/CreatePostActivity.kt +++ b/app/src/main/java/com/isolaatti/posting/posts/ui/CreatePostActivity.kt @@ -1,14 +1,10 @@ package com.isolaatti.posting.posts.ui import android.app.Activity -import android.content.Context import android.content.Intent import android.os.Bundle -import android.os.PersistableBundle import android.view.View import androidx.activity.viewModels -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.res.ResourcesCompat import androidx.core.widget.doOnTextChanged import com.isolaatti.R import com.isolaatti.common.IsolaattiBaseActivity @@ -32,14 +28,6 @@ class CreatePostActivity : IsolaattiBaseActivity() { const val EXTRA_KEY_POST_ID = "postId" const val EXTRA_KEY_POST_POSTED = "post" - - fun startActivityEditMode(context: Context, postId: Long) { - val intent = Intent(context, CreatePostActivity::class.java).apply { - putExtra(EXTRA_KEY_MODE, EXTRA_MODE_EDIT) - putExtra(EXTRA_KEY_POST_ID, postId) - } - context.startActivity(intent) - } } lateinit var binding: ActivityCreatePostBinding @@ -65,6 +53,10 @@ class CreatePostActivity : IsolaattiBaseActivity() { binding = ActivityCreatePostBinding.inflate(layoutInflater) + if(mode == EXTRA_MODE_EDIT && postId != 0L) { + viewModel.loadDiscussion(postId) + } + setupUI() @@ -117,6 +109,10 @@ class CreatePostActivity : IsolaattiBaseActivity() { viewModel.loading.observe(this@CreatePostActivity) { binding.progressBarLoading.visibility = if(it) View.VISIBLE else View.GONE } + + viewModel.postToEdit.observe(this) { + binding.filledTextField.editText?.setText(it.content) + } } private fun exit() {