crear reportes
This commit is contained in:
parent
ce8ec23100
commit
bf886c845d
@ -36,6 +36,7 @@ import com.isolaatti.images.image_chooser.ui.ImageChooserContract
|
|||||||
import com.isolaatti.posting.link_creator.presentation.LinkCreatorViewModel
|
import com.isolaatti.posting.link_creator.presentation.LinkCreatorViewModel
|
||||||
import com.isolaatti.posting.link_creator.ui.LinkCreatorFragment
|
import com.isolaatti.posting.link_creator.ui.LinkCreatorFragment
|
||||||
import com.isolaatti.profile.ui.ProfileActivity
|
import com.isolaatti.profile.ui.ProfileActivity
|
||||||
|
import com.isolaatti.reports.data.ContentType
|
||||||
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin
|
import io.noties.markwon.AbstractMarkwonPlugin
|
||||||
@ -75,7 +76,8 @@ class BottomSheetPostComments() : BottomSheetDialogFragment(), OnUserInteractedC
|
|||||||
}
|
}
|
||||||
Options.Option.OPTION_REPORT -> {
|
Options.Option.OPTION_REPORT -> {
|
||||||
optionsViewModel.handle()
|
optionsViewModel.handle()
|
||||||
NewReportBottomSheetDialogFragment.newInstance().show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Comment, comment.id.toString())
|
||||||
|
.show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ import com.isolaatti.posting.posts.presentation.PostListingViewModel
|
|||||||
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
import com.isolaatti.posting.posts.presentation.PostsRecyclerViewAdapter
|
||||||
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
||||||
import com.isolaatti.profile.ui.ProfileActivity
|
import com.isolaatti.profile.ui.ProfileActivity
|
||||||
|
import com.isolaatti.reports.data.ContentType
|
||||||
|
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.noties.markwon.AbstractMarkwonPlugin
|
import io.noties.markwon.AbstractMarkwonPlugin
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
@ -209,6 +211,8 @@ class PostListingFragment : Fragment(), OnUserInteractedWithPostCallback {
|
|||||||
}
|
}
|
||||||
Options.Option.OPTION_REPORT -> {
|
Options.Option.OPTION_REPORT -> {
|
||||||
optionsViewModel.handle()
|
optionsViewModel.handle()
|
||||||
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Post, post.id.toString())
|
||||||
|
.show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,6 +49,7 @@ import com.isolaatti.posting.posts.viewer.ui.PostViewerActivity
|
|||||||
import com.isolaatti.profile.domain.entity.UserProfile
|
import com.isolaatti.profile.domain.entity.UserProfile
|
||||||
import com.isolaatti.profile.presentation.EditProfileContract
|
import com.isolaatti.profile.presentation.EditProfileContract
|
||||||
import com.isolaatti.profile.presentation.ProfileViewModel
|
import com.isolaatti.profile.presentation.ProfileViewModel
|
||||||
|
import com.isolaatti.reports.data.ContentType
|
||||||
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
import com.isolaatti.reports.ui.NewReportBottomSheetDialogFragment
|
||||||
import com.isolaatti.utils.UrlGen
|
import com.isolaatti.utils.UrlGen
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@ -266,7 +267,7 @@ class ProfileMainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
Options.Option.OPTION_REPORT -> {
|
Options.Option.OPTION_REPORT -> {
|
||||||
optionsViewModel.handle()
|
optionsViewModel.handle()
|
||||||
NewReportBottomSheetDialogFragment.newInstance().show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Post, post.id.toString()).show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,6 +330,7 @@ class ProfileMainFragment : Fragment() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.report_profile_menu_item -> {
|
R.id.report_profile_menu_item -> {
|
||||||
|
NewReportBottomSheetDialogFragment.newInstance(ContentType.Profile, viewModel.profileId.toString()).show(childFragmentManager, NewReportBottomSheetDialogFragment.LOG_TAG)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.block_profile_menu_item -> {
|
R.id.block_profile_menu_item -> {
|
||||||
|
|||||||
24
app/src/main/java/com/isolaatti/reports/Module.kt
Normal file
24
app/src/main/java/com/isolaatti/reports/Module.kt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package com.isolaatti.reports
|
||||||
|
|
||||||
|
import com.isolaatti.connectivity.RetrofitClient
|
||||||
|
import com.isolaatti.reports.data.ReportsApi
|
||||||
|
import com.isolaatti.reports.data.ReportsRepositoryImpl
|
||||||
|
import com.isolaatti.reports.domain.ReportsRepository
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
class Module {
|
||||||
|
@Provides
|
||||||
|
fun provideReportsApi(retrofitClient: RetrofitClient): ReportsApi {
|
||||||
|
return retrofitClient.client.create(ReportsApi::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideReportsRepository(reportsApi: ReportsApi): ReportsRepository {
|
||||||
|
return ReportsRepositoryImpl(reportsApi)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.isolaatti.reports.data
|
||||||
|
|
||||||
|
data class CreateReportDto(
|
||||||
|
val reason: Int,
|
||||||
|
val comment: String,
|
||||||
|
val contentType: Int,
|
||||||
|
val contentId: String
|
||||||
|
)
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.isolaatti.reports.data
|
||||||
|
|
||||||
|
data class ReportDto(
|
||||||
|
val id: String,
|
||||||
|
val reportReason: Int,
|
||||||
|
val userId: Int,
|
||||||
|
val userComment: String,
|
||||||
|
val status: Int
|
||||||
|
)
|
||||||
12
app/src/main/java/com/isolaatti/reports/data/ReportEnums.kt
Normal file
12
app/src/main/java/com/isolaatti/reports/data/ReportEnums.kt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package com.isolaatti.reports.data
|
||||||
|
|
||||||
|
// keep enum constants in this specific order
|
||||||
|
|
||||||
|
|
||||||
|
enum class ContentType {
|
||||||
|
Post, Comment, Profile, Squad, Picture, Audio
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ReportStatus {
|
||||||
|
Open, Resolved, InReview
|
||||||
|
}
|
||||||
16
app/src/main/java/com/isolaatti/reports/data/ReportsApi.kt
Normal file
16
app/src/main/java/com/isolaatti/reports/data/ReportsApi.kt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.isolaatti.reports.data
|
||||||
|
|
||||||
|
import com.isolaatti.common.ResultDto
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.POST
|
||||||
|
|
||||||
|
interface ReportsApi {
|
||||||
|
|
||||||
|
@POST("reports")
|
||||||
|
fun createReport(@Body createReportDto: CreateReportDto): Call<ReportDto>
|
||||||
|
|
||||||
|
@GET("reports/by_me")
|
||||||
|
fun gerReportsByMe(): Call<ResultDto<ReportDto>>
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.isolaatti.reports.data
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import com.isolaatti.reports.domain.ReportsRepository
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import retrofit2.awaitResponse
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ReportsRepositoryImpl @Inject constructor(private val reportsApi: ReportsApi) : ReportsRepository {
|
||||||
|
companion object {
|
||||||
|
const val LOG_TAG = "ReportsRepositoryImpl"
|
||||||
|
}
|
||||||
|
override fun createReport(createReportDto: CreateReportDto): Flow<Resource<ReportDto>> = flow {
|
||||||
|
try {
|
||||||
|
emit(Resource.Loading())
|
||||||
|
val response = reportsApi.createReport(createReportDto).awaitResponse()
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
emit(Resource.Success(response.body()))
|
||||||
|
} else {
|
||||||
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
|
}
|
||||||
|
} catch(e: Exception) {
|
||||||
|
Log.e(LOG_TAG, "error creating report: ${e.message}")
|
||||||
|
emit(Resource.Error(Resource.Error.ErrorType.OtherError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getReportsByMe(): Flow<Resource<List<ReportDto>>> {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.isolaatti.reports.domain
|
||||||
|
|
||||||
|
import com.isolaatti.reports.data.CreateReportDto
|
||||||
|
import com.isolaatti.reports.data.ReportDto
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface ReportsRepository {
|
||||||
|
fun createReport(createReportDto: CreateReportDto): Flow<Resource<ReportDto>>
|
||||||
|
|
||||||
|
fun getReportsByMe(): Flow<Resource<List<ReportDto>>>
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.isolaatti.reports.presentation
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.isolaatti.reports.data.ContentType
|
||||||
|
import com.isolaatti.reports.data.CreateReportDto
|
||||||
|
import com.isolaatti.reports.data.ReportDto
|
||||||
|
import com.isolaatti.reports.domain.ReportsRepository
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class CreateReportViewModel @Inject constructor(private val reportsRepository: ReportsRepository) : ViewModel() {
|
||||||
|
val createReportResponse: MutableLiveData<Resource<ReportDto>> = MutableLiveData()
|
||||||
|
|
||||||
|
fun createReport(reason: Int, comment: String, contentType: ContentType, contentId: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
reportsRepository.createReport(CreateReportDto(reason, comment, contentType.ordinal, contentId)).onEach {
|
||||||
|
createReportResponse.postValue(it)
|
||||||
|
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,12 +4,33 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.core.widget.doOnTextChanged
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
|
import com.isolaatti.R
|
||||||
import com.isolaatti.databinding.BottomSheetNewReportBinding
|
import com.isolaatti.databinding.BottomSheetNewReportBinding
|
||||||
|
import com.isolaatti.reports.data.ContentType
|
||||||
|
import com.isolaatti.reports.presentation.CreateReportViewModel
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
class NewReportBottomSheetDialogFragment : BottomSheetDialogFragment() {
|
class NewReportBottomSheetDialogFragment : BottomSheetDialogFragment() {
|
||||||
|
|
||||||
private lateinit var binding: BottomSheetNewReportBinding
|
private lateinit var binding: BottomSheetNewReportBinding
|
||||||
|
private val viewModel: CreateReportViewModel by viewModels()
|
||||||
|
|
||||||
|
private lateinit var contentType: ContentType
|
||||||
|
private lateinit var contentId: String
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
contentType = arguments?.getSerializable(ARG_CONTENT_TYPE) as ContentType
|
||||||
|
contentId = arguments?.getString(ARG_CONTENT_ID)!!
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
@ -21,10 +42,45 @@ class NewReportBottomSheetDialogFragment : BottomSheetDialogFragment() {
|
|||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
ArrayAdapter.createFromResource(requireContext(), R.array.report_reasons, android.R.layout.simple_spinner_item).also { spinnerAdapter ->
|
||||||
|
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||||
|
binding.reportReasons.adapter = spinnerAdapter
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.reportUserComment.editText?.doOnTextChanged { text, start, before, count ->
|
||||||
|
binding.submitReportButton.isEnabled = count > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.submitReportButton.setOnClickListener {
|
||||||
|
viewModel.createReport(binding.reportReasons.selectedItemPosition, binding.reportUserComment.editText?.text.toString(), contentType, contentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.createReportResponse.observe(viewLifecycleOwner) { resource ->
|
||||||
|
when(resource) {
|
||||||
|
is Resource.Error -> {}
|
||||||
|
is Resource.Loading -> {}
|
||||||
|
is Resource.Success -> {
|
||||||
|
Toast.makeText(requireContext(), R.string.report_submitted_successfully, Toast.LENGTH_SHORT).show()
|
||||||
|
dialog?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val LOG_TAG = "NewReportBottomSheetDialogFragment"
|
const val LOG_TAG = "NewReportBottomSheetDialogFragment"
|
||||||
fun newInstance(): NewReportBottomSheetDialogFragment {
|
const val ARG_CONTENT_TYPE = "contentType"
|
||||||
return NewReportBottomSheetDialogFragment()
|
const val ARG_CONTENT_ID = "contentId"
|
||||||
|
fun newInstance(contentType: ContentType, contentId: String): NewReportBottomSheetDialogFragment {
|
||||||
|
return NewReportBottomSheetDialogFragment().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putSerializable(ARG_CONTENT_TYPE, contentType)
|
||||||
|
putString(ARG_CONTENT_ID, contentId)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,27 +22,21 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@id/drag_handle"/>
|
app:layout_constraintTop_toBottomOf="@id/drag_handle"/>
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<Spinner
|
||||||
android:id="@+id/menu"
|
android:id="@+id/report_reasons"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toBottomOf="@id/title"
|
app:layout_constraintTop_toBottomOf="@id/title"
|
||||||
android:layout_marginHorizontal="16dp"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:layout_marginTop="16dp">
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
<AutoCompleteTextView
|
android:layout_marginHorizontal="16dp"/>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/textField"
|
android:id="@+id/report_user_comment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toBottomOf="@id/menu"
|
app:layout_constraintTop_toBottomOf="@id/report_reasons"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginHorizontal="16dp">
|
android:layout_marginHorizontal="16dp">
|
||||||
|
|
||||||
@ -55,15 +49,17 @@
|
|||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/submit_report_button"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Submit report"
|
android:text="Submit report"
|
||||||
app:layout_constraintTop_toBottomOf="@id/textField"
|
app:layout_constraintTop_toBottomOf="@id/report_user_comment"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginHorizontal="16dp"
|
android:layout_marginHorizontal="16dp"
|
||||||
app:layout_goneMarginTop="16dp"
|
app:layout_goneMarginTop="16dp"
|
||||||
|
android:enabled="false"
|
||||||
style="?attr/materialIconButtonFilledTonalStyle"/>
|
style="?attr/materialIconButtonFilledTonalStyle"/>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@ -205,4 +205,16 @@
|
|||||||
<string name="browse_profiles">Browse profiles</string>
|
<string name="browse_profiles">Browse profiles</string>
|
||||||
<string name="app_version">v%s</string>
|
<string name="app_version">v%s</string>
|
||||||
<string name="new_report">New report</string>
|
<string name="new_report">New report</string>
|
||||||
|
<string name="report_submitted_successfully">Report submitted successfully</string>
|
||||||
|
<string-array name="report_reasons">
|
||||||
|
<item>Spam</item>
|
||||||
|
<item>Explicit content</item>
|
||||||
|
<item>Children at risk</item>
|
||||||
|
<item>Piracy</item>
|
||||||
|
<item>Copyright protected content</item>
|
||||||
|
<item>Hate and/or discrimination</item>
|
||||||
|
<item>Identity fraud</item>
|
||||||
|
<item>Fraudulent IA generated content</item>
|
||||||
|
<item>People in danger</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
x
Reference in New Issue
Block a user