This commit is contained in:
erike 2023-08-25 00:18:32 -06:00
parent 1e02f0bc6f
commit f91fa2d27d
12 changed files with 141 additions and 22 deletions

View File

@ -11,5 +11,6 @@ object Dialogs {
.setMessage(R.string.post_will_dropped) .setMessage(R.string.post_will_dropped)
.setPositiveButton(R.string.yes_continue) {_, _ -> onContinue(true)} .setPositiveButton(R.string.yes_continue) {_, _ -> onContinue(true)}
.setNegativeButton(R.string.cancel) { _, _ -> onContinue(false)} .setNegativeButton(R.string.cancel) { _, _ -> onContinue(false)}
.setOnCancelListener { onContinue(false) }
} }
} }

View File

@ -1,6 +1,5 @@
package com.isolaatti.home package com.isolaatti.home
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
@ -10,7 +9,6 @@ import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer 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.domain.Options
import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel import com.isolaatti.posting.common.options_bottom_sheet.presentation.BottomSheetPostOptionsViewModel
import com.isolaatti.posting.common.options_bottom_sheet.ui.BottomSheetPostOptionsFragment 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.presentation.PostsRecyclerViewAdapter
import com.isolaatti.posting.posts.ui.CreatePostActivity
import com.isolaatti.profile.ui.ProfileActivity import com.isolaatti.profile.ui.ProfileActivity
import com.isolaatti.settings.ui.SettingsActivity import com.isolaatti.settings.ui.SettingsActivity
import com.isolaatti.utils.PicassoImagesPluginDef import com.isolaatti.utils.PicassoImagesPluginDef
@ -62,12 +61,24 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
private lateinit var viewBinding: FragmentFeedBinding private lateinit var viewBinding: FragmentFeedBinding
private lateinit var adapter: PostsRecyclerViewAdapter private lateinit var adapter: PostsRecyclerViewAdapter
private val createDiscussion = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { // region launchers
if(it.resultCode == Activity.RESULT_OK) {
private val createDiscussion = registerForActivityResult(CreatePostContract()) {
if(it != null) {
Toast.makeText(requireContext(), R.string.posted_successfully, Toast.LENGTH_SHORT).show() 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<OptionClicked?> = Observer { optionClicked -> val optionsObserver: Observer<OptionClicked?> = Observer { optionClicked ->
if(optionClicked?.callerId == CALLER_ID) { if(optionClicked?.callerId == CALLER_ID) {
// post id should come as payload // post id should come as payload
@ -84,7 +95,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
} }
Options.Option.OPTION_EDIT -> { Options.Option.OPTION_EDIT -> {
optionsViewModel.handle() optionsViewModel.handle()
CreatePostActivity.startActivityEditMode(requireContext(), postId) editDiscussion.launch(postId)
} }
Options.Option.OPTION_REPORT -> { Options.Option.OPTION_REPORT -> {
@ -93,6 +104,9 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
} }
} }
// endregion
// region lifecycle
override fun onCreateView( override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
@ -102,6 +116,9 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
return viewBinding.root return viewBinding.root
} }
// endregion
// region events
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
viewBinding.topAppBar.setNavigationOnClickListener { viewBinding.topAppBar.setNavigationOnClickListener {
@ -156,7 +173,7 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
viewBinding.topAppBar.setOnMenuItemClickListener { viewBinding.topAppBar.setOnMenuItemClickListener {
when(it.itemId) { when(it.itemId) {
R.id.menu_item_new_discussion -> { R.id.menu_item_new_discussion -> {
createDiscussion.launch(Intent(requireContext(),CreatePostActivity::class.java)) createDiscussion.launch(Unit)
true true
} }
else -> { else -> {
@ -232,4 +249,6 @@ class FeedFragment : Fragment(), OnUserInteractedWithPostCallback {
override fun onLoadMore() { override fun onLoadMore() {
viewModel.getFeed(false) viewModel.getFeed(false)
} }
// endregion
} }

View File

@ -3,8 +3,8 @@ package com.isolaatti.posting.posts.data.remote
data class EditPostDto( data class EditPostDto(
val privacy: Int, val privacy: Int,
val content: String, val content: String,
val audioId: String?, val audioId: String? = null,
val squadId: String?, val squadId: String? = null,
val postId: Long val postId: Long
) { ) {
companion object { companion object {

View File

@ -2,7 +2,9 @@ package com.isolaatti.posting.posts.data.remote
import retrofit2.Call import retrofit2.Call
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Path
interface PostApi { interface PostApi {
@POST("Posting/Make") @POST("Posting/Make")
@ -14,4 +16,7 @@ interface PostApi {
@POST("Posting/Delete") @POST("Posting/Delete")
fun deletePost(@Body postToDelete: DeletePostDto): Call<PostDeletedDto> fun deletePost(@Body postToDelete: DeletePostDto): Call<PostDeletedDto>
@GET("Fetch/Post/{postId}")
fun getPost(@Path("postId") postId: Long): Call<FeedDto.PostDto>
} }

View File

@ -111,4 +111,23 @@ class PostsRepositoryImpl @Inject constructor(private val feedsApi: FeedsApi, pr
emit(Resource.Error(Resource.Error.ErrorType.NetworkError)) emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
} }
} }
override fun loadPost(postId: Long): Flow<Resource<FeedDto.PostDto>> = 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))
}
}
} }

View File

@ -17,4 +17,5 @@ interface PostsRepository {
fun makePost(createPostDto: CreatePostDto): Flow<Resource<FeedDto.PostDto>> fun makePost(createPostDto: CreatePostDto): Flow<Resource<FeedDto.PostDto>>
fun editPost(editPostDto: EditPostDto): Flow<Resource<FeedDto.PostDto>> fun editPost(editPostDto: EditPostDto): Flow<Resource<FeedDto.PostDto>>
fun deletePost(postId: Long): Flow<Resource<PostDeletedDto>> fun deletePost(postId: Long): Flow<Resource<PostDeletedDto>>
fun loadPost(postId: Long): Flow<Resource<FeedDto.PostDto>>
} }

View File

@ -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<Resource<FeedDto.PostDto>> {
return postsRepository.loadPost(postId)
}
}

View File

@ -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<Unit, FeedDto.PostDto?>() {
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
}
}
}

View File

@ -5,8 +5,10 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.isolaatti.posting.posts.data.remote.CreatePostDto import com.isolaatti.posting.posts.data.remote.CreatePostDto
import com.isolaatti.posting.posts.data.remote.EditPostDto 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.data.remote.FeedDto
import com.isolaatti.posting.posts.domain.use_case.EditPost 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.posting.posts.domain.use_case.MakePost
import com.isolaatti.utils.Resource import com.isolaatti.utils.Resource
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -18,11 +20,12 @@ import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @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<Boolean> = MutableLiveData(false) val validation: MutableLiveData<Boolean> = MutableLiveData(false)
val posted: MutableLiveData<FeedDto.PostDto?> = MutableLiveData() val posted: MutableLiveData<FeedDto.PostDto?> = MutableLiveData()
val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData() val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData()
val loading: MutableLiveData<Boolean> = MutableLiveData(false) val loading: MutableLiveData<Boolean> = MutableLiveData(false)
val postToEdit: MutableLiveData<EditPostDto> = MutableLiveData()
fun postDiscussion(content: String) { fun postDiscussion(content: String) {
viewModelScope.launch { 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)
}
}
} }

View File

@ -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<Long, FeedDto.PostDto?>() {
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
}
}
}

View File

@ -93,4 +93,8 @@ abstract class PostListingViewModelBase : ViewModel() {
}.flowOn(Dispatchers.IO).launchIn(this) }.flowOn(Dispatchers.IO).launchIn(this)
} }
} }
fun onPostUpdate(post: FeedDto.PostDto) {
}
} }

View File

@ -1,14 +1,10 @@
package com.isolaatti.posting.posts.ui package com.isolaatti.posting.posts.ui
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.PersistableBundle
import android.view.View import android.view.View
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import com.isolaatti.R import com.isolaatti.R
import com.isolaatti.common.IsolaattiBaseActivity import com.isolaatti.common.IsolaattiBaseActivity
@ -32,14 +28,6 @@ class CreatePostActivity : IsolaattiBaseActivity() {
const val EXTRA_KEY_POST_ID = "postId" const val EXTRA_KEY_POST_ID = "postId"
const val EXTRA_KEY_POST_POSTED = "post" 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 lateinit var binding: ActivityCreatePostBinding
@ -65,6 +53,10 @@ class CreatePostActivity : IsolaattiBaseActivity() {
binding = ActivityCreatePostBinding.inflate(layoutInflater) binding = ActivityCreatePostBinding.inflate(layoutInflater)
if(mode == EXTRA_MODE_EDIT && postId != 0L) {
viewModel.loadDiscussion(postId)
}
setupUI() setupUI()
@ -117,6 +109,10 @@ class CreatePostActivity : IsolaattiBaseActivity() {
viewModel.loading.observe(this@CreatePostActivity) { viewModel.loading.observe(this@CreatePostActivity) {
binding.progressBarLoading.visibility = if(it) View.VISIBLE else View.GONE binding.progressBarLoading.visibility = if(it) View.VISIBLE else View.GONE
} }
viewModel.postToEdit.observe(this) {
binding.filledTextField.editText?.setText(it.content)
}
} }
private fun exit() { private fun exit() {